<?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: Abid niazi</title>
    <description>The latest articles on DEV Community by Abid niazi (@abid_niazi_a7faa6246a7952).</description>
    <link>https://dev.to/abid_niazi_a7faa6246a7952</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%2F3894279%2F1c0050ad-e1a9-472a-891b-955def09cd9e.png</url>
      <title>DEV Community: Abid niazi</title>
      <link>https://dev.to/abid_niazi_a7faa6246a7952</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abid_niazi_a7faa6246a7952"/>
    <language>en</language>
    <item>
      <title>10 free online tools every developer should bookmark in 2025</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Sat, 30 May 2026 13:16:27 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/10-free-online-tools-every-developer-should-bookmark-in-2025-4364</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/10-free-online-tools-every-developer-should-bookmark-in-2025-4364</guid>
      <description>&lt;p&gt;Hi Muhammad abid,&lt;/p&gt;

&lt;p&gt;I've been following free tool forge  for a while and noticed you publish practical tooling guides for developers. I'd love to contribute a guest post titled:&lt;/p&gt;

&lt;p&gt;"10 free online tools every developer should bookmark in 2025"&lt;/p&gt;

&lt;p&gt;Here's a quick outline:&lt;/p&gt;

&lt;p&gt;— Introduction: why free tools close the gap between idea and execution&lt;br&gt;
— Section 1: Text &amp;amp; data tools (JSON formatters, regex testers, diff checkers)&lt;br&gt;
— Section 2: Code &amp;amp; API tools (curl converters, HTTP status checkers, Base64 encoders)&lt;br&gt;
— Section 3: Design &amp;amp; image tools (SVG optimisers, color pickers, favicon generators)&lt;br&gt;
— Section 4: Productivity &amp;amp; workflow tools&lt;br&gt;
— Section 5: Where to find more — including [&lt;a href="https://freetoolforge.org/" rel="noopener noreferrer"&gt;https://freetoolforge.org/&lt;/a&gt;], a directory of free browser tools with no signup required&lt;br&gt;
— Conclusion: building a personal toolbox&lt;/p&gt;

&lt;p&gt;The piece would be 100% original, around 1,200 words, with practical screenshots. I can include 1–2 contextual links to your own content as well.&lt;/p&gt;

&lt;p&gt;Would this be a good fit? Happy to adjust the angle to suit your audience.&lt;/p&gt;

&lt;p&gt;free tool forge &lt;br&gt;
&lt;a href="https://freetoolforge.org/" rel="noopener noreferrer"&gt;https://freetoolforge.org/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How Dual-URL Architecture Doubled My Indexed Pages (Next.js 14 SEO Strategy)</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Thu, 21 May 2026 16:48:39 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/how-dual-url-architecture-doubled-my-indexed-pages-nextjs-14-seo-strategy-4fl1</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/how-dual-url-architecture-doubled-my-indexed-pages-nextjs-14-seo-strategy-4fl1</guid>
      <description>&lt;p&gt;After 4 months of building &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;ToolForge&lt;/a&gt;, I have 152 organic keywords growing at +2,071%. Here's the single architectural decision that made the biggest difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I built an online calculator. Let's say an EMI Calculator. It lives at:&lt;br&gt;
/tools/calculators/emi-calculator&lt;/p&gt;

&lt;p&gt;This page targets &lt;strong&gt;action keywords&lt;/strong&gt; — people who type "emi calculator" into Google. They want to USE the tool.&lt;/p&gt;

&lt;p&gt;But there's a second group: people who type "how to calculate emi in pakistan." They want to LEARN. They'll spend 5-10 minutes reading before they need a calculator.&lt;/p&gt;

&lt;p&gt;One URL can't serve both intents well. A tool page with a 3,000-word guide has terrible UX. A guide page with an embedded calculator is slow and unfocused.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution: Dual URLs Per Tool
&lt;/h2&gt;

&lt;p&gt;Every tool in ToolForge gets two pages:&lt;br&gt;
/tools/calculators/emi-calculator    ← Interactive tool&lt;br&gt;
/emi-calculator                       ← Long-form SEO guide&lt;/p&gt;

&lt;p&gt;In Next.js 14 App Router, this means:&lt;br&gt;
src/app/tools/calculators/emi-calculator/page.tsx   ← 'use client', interactive&lt;br&gt;
src/app/emi-calculator/page.tsx                      ← server component, 3000+ words&lt;/p&gt;

&lt;p&gt;The tool page is a client component with state, inputs, and instant results. The guide page is a server-rendered article with headings, tables, FAQs, and schema markup.&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works for SEO
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tool page&lt;/strong&gt; (&lt;code&gt;/tools/calculators/emi-calculator&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Targets: "emi calculator", "loan calculator", "emi calculator pakistan"&lt;/li&gt;
&lt;li&gt;Schema: &lt;code&gt;SoftwareApplication&lt;/code&gt; JSON-LD&lt;/li&gt;
&lt;li&gt;Content: minimal — just the tool + brief instructions&lt;/li&gt;
&lt;li&gt;User intent: DO something&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Guide page&lt;/strong&gt; (&lt;code&gt;/emi-calculator&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Targets: "how to calculate emi", "emi formula", "bank loan rates pakistan"&lt;/li&gt;
&lt;li&gt;Schema: &lt;code&gt;FAQPage&lt;/code&gt; JSON-LD
&lt;/li&gt;
&lt;li&gt;Content: 3,000+ words — formula explanation, bank comparisons, tips, FAQs&lt;/li&gt;
&lt;li&gt;User intent: LEARN something&lt;/li&gt;
&lt;li&gt;Contains a prominent CTA button linking to the tool page&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Results
&lt;/h2&gt;

&lt;p&gt;From 61 tools, this architecture generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;61 tool pages (action keywords)&lt;/li&gt;
&lt;li&gt;61 guide pages (informational keywords)
&lt;/li&gt;
&lt;li&gt;= 122 indexable pages from the same number of tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our sitemap has 100+ URLs. Google has indexed 86 so far, and we're ranking for 152 keywords.&lt;/p&gt;

&lt;p&gt;The guide pages consistently rank higher than tool pages because Google favors comprehensive content for informational queries. But the tool pages capture direct-intent traffic from people who just want a calculator.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation Pattern
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tool page&lt;/strong&gt; (client 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="c1"&gt;// src/app/tools/calculators/emi-calculator/page.tsx&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&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="nx"&gt;RelatedTools&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/components/ui/RelatedTools&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;EMICalculator&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="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;setAmount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setRate&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ... calculator logic&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"max-w-4xl mx-auto p-6"&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;EMI Calculator&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Interactive inputs + results */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RelatedTools&lt;/span&gt; &lt;span class="na"&gt;recommendedIds&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;business-loan-calculator&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;fbr-tax-calculator&lt;/span&gt;&lt;span class="dl"&gt;'&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="nt"&gt;div&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;&lt;strong&gt;Guide page&lt;/strong&gt; (server 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="c1"&gt;// src/app/emi-calculator/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/link&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;EMIGuide&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;article&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"max-w-4xl mx-auto p-6"&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;How to Calculate EMI in Pakistan 2026&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* CTA to the actual tool */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/tools/calculators/emi-calculator"&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-indigo-600 px-6 py-3 rounded-xl text-white"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Calculate Your EMI Now →
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* 3,000+ words of guide content */&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;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;What is EMI?&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;EMI stands for Equated Monthly Installment...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* FAQs with schema markup */&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;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Frequently Asked Questions&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&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;article&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;&lt;strong&gt;Layout&lt;/strong&gt; (metadata for each):&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;// src/app/tools/calculators/emi-calculator/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EMI Calculator — Free Loan EMI Calculator Pakistan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Calculate your monthly EMI instantly...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;alternates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://freetoolforge.org/tools/calculators/emi-calculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// src/app/emi-calculator/layout.tsx  &lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;How to Calculate EMI in Pakistan 2026 — Complete Guide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Learn how EMI is calculated with formula...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;alternates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://freetoolforge.org/emi-calculator&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different canonical URLs, different titles, different meta descriptions. Google treats them as separate pages targeting different keywords.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cross-Linking Strategy
&lt;/h2&gt;

&lt;p&gt;The guide page links to the tool: "Calculate your EMI instantly →"&lt;br&gt;
The tool page links to the guide via a &lt;code&gt;DocButton&lt;/code&gt; component: "Read the full guide →"&lt;/p&gt;

&lt;p&gt;This creates a bidirectional internal link loop that passes authority between both pages. When the guide ranks well, it boosts the tool. When the tool ranks well, it boosts the guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  When NOT to Use Dual URLs
&lt;/h2&gt;

&lt;p&gt;Not every tool needs a guide. If the tool is self-explanatory (like a UUID Generator), the guide page would be thin content — which hurts SEO.&lt;/p&gt;

&lt;p&gt;Use dual URLs when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The topic has informational search intent ("how to...")&lt;/li&gt;
&lt;li&gt;You can write 1,500+ words of genuine, useful content&lt;/li&gt;
&lt;li&gt;The tool targets a different keyword than the guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Skip the guide when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The tool is self-explanatory (Base64 encoder, color picker)&lt;/li&gt;
&lt;li&gt;You'd be padding content just to fill the page&lt;/li&gt;
&lt;li&gt;The keyword volume for "how to" queries is under 100/month&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The entire architecture is live at &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt;. You can see the pattern in action:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool: &lt;a href="https://freetoolforge.org/tools/calculators/nust-merit-calculator" rel="noopener noreferrer"&gt;NUST Merit Calculator&lt;/a&gt; → Guide: &lt;a href="https://freetoolforge.org/nust-merit-calculator" rel="noopener noreferrer"&gt;How to Calculate NUST Aggregate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tool: &lt;a href="https://freetoolforge.org/tools/text-tools/ai-essay-writer" rel="noopener noreferrer"&gt;AI Essay Writer&lt;/a&gt; → Guide: &lt;a href="https://freetoolforge.org/ai-essay-writer" rel="noopener noreferrer"&gt;AI Essay Writer Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tool: &lt;a href="https://freetoolforge.org/tools/calculators/fbr-tax-calculator" rel="noopener noreferrer"&gt;FBR Tax Calculator&lt;/a&gt; → Guide: &lt;a href="https://freetoolforge.org/fbr-tax-calculator" rel="noopener noreferrer"&gt;FBR Tax Guide&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;61 tools × 2 URLs = 122 pages. The dual-URL architecture is the single biggest SEO lever we've pulled.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/abidniazi" rel="noopener noreferrer"&gt;Abid Niazi&lt;/a&gt; — Full Stack Developer, Pakistan&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt; — 61 free tools, zero ads&lt;/em&gt;&lt;a href="https://dev.tourl"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Handle 150K Free API Calls/Month with a 5-Key Rotation System in Next.js</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Thu, 21 May 2026 16:46:32 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/how-i-handle-150k-free-api-callsmonth-with-a-5-key-rotation-system-in-nextjs-3cda</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/how-i-handle-150k-free-api-callsmonth-with-a-5-key-rotation-system-in-nextjs-3cda</guid>
      <description>&lt;p&gt;Most free-tier APIs give you 15 requests/minute. That's fine for a side project — until your tools start getting real traffic.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;ToolForge&lt;/a&gt;, a free toolkit with 61 tools including 4 AI-powered features (summarizer, grammar checker, paraphraser, essay writer). All powered by Google Gemini's free tier.&lt;/p&gt;

&lt;p&gt;The challenge: 15 req/min × 1 key = dead tool after 15 users.&lt;/p&gt;

&lt;p&gt;The solution: rotate across 5 API keys with automatic failover.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Gemini's free tier is generous — 15 requests per minute, 1,500 per day per key. But a single key means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User #16 in any given minute gets a 429 error&lt;/li&gt;
&lt;li&gt;Your "free AI tool" stops working during peak hours&lt;/li&gt;
&lt;li&gt;Users lose trust and never come back&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I needed a system that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Distributes requests across multiple keys&lt;/li&gt;
&lt;li&gt;Automatically skips rate-limited keys&lt;/li&gt;
&lt;li&gt;Never shows a 429 to the end user&lt;/li&gt;
&lt;li&gt;Works without any external state management&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Solution: Round-Robin with Failover
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/gemini-keys.ts (simplified)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_KEYS&lt;/span&gt; &lt;span class="o"&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;GEMINI_API_KEY_1&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;GEMINI_API_KEY_2&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;GEMINI_API_KEY_3&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;GEMINI_API_KEY_4&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;GEMINI_API_KEY_5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;currentKeyIndex&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="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;fetchWithKeyRotation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&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;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gemini-2.5-flash-lite&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxAttempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;API_KEYS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;attempt&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;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;maxAttempts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;attempt&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;API_KEYS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentKeyIndex&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`https://generativelanguage.googleapis.com/v1beta/models/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:generateContent`&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="s1"&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;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-goog-api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="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="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
          &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&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;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Rate limited — rotate to next key&lt;/span&gt;
        &lt;span class="nx"&gt;currentKeyIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentKeyIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;API_KEYS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;continue&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;ok&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;`API error: &lt;/span&gt;&lt;span class="p"&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;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="c1"&gt;// Success — rotate for next request (spread load)&lt;/span&gt;
      &lt;span class="nx"&gt;currentKeyIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentKeyIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;API_KEYS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;data&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;response&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="k"&gt;return&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;candidates&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;text&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="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="nx"&gt;currentKeyIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentKeyIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;API_KEYS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;attempt&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;maxAttempts&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;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="s1"&gt;All API keys exhausted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Round-robin by default&lt;/strong&gt;: Each request uses the next key in sequence. This spreads load evenly — key 1 handles request 1, key 2 handles request 2, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic failover on 429&lt;/strong&gt;: If a key is rate-limited, the loop immediately tries the next key. No delay, no retry timer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wraps around&lt;/strong&gt;: After key 5, it goes back to key 1. The modulo operator handles this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No external state&lt;/strong&gt;: &lt;code&gt;currentKeyIndex&lt;/code&gt; lives in server memory. For a single Vercel serverless function, this works perfectly. For multi-instance deployments, you'd want Redis — but for our scale, this is enough.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Math
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Keys&lt;/th&gt;
&lt;th&gt;Requests/Min&lt;/th&gt;
&lt;th&gt;Requests/Day&lt;/th&gt;
&lt;th&gt;Requests/Month&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 key&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;1,500&lt;/td&gt;
&lt;td&gt;45,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3 keys&lt;/td&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;4,500&lt;/td&gt;
&lt;td&gt;135,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;5 keys&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;75&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;7,500&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;225,000&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;With 5 keys, we handle 75 simultaneous requests per minute and 225,000 per month — all on the free tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using It in API Routes
&lt;/h2&gt;

&lt;p&gt;Every AI tool calls the same function:&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;// src/app/api/summarize/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;fetchWithKeyRotation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/lib/gemini-keys&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;text&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;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Summarize the following text in 3-5 sentences:\n\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchWithKeyRotation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&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="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;summary&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The AI Summarizer, Grammar Checker, Paraphraser, and Essay Writer all use the exact same &lt;code&gt;fetchWithKeyRotation()&lt;/code&gt; function. Adding a new AI tool takes 10 minutes — just create a new API route with a different prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rate Limiting Users (Not Just Keys)
&lt;/h2&gt;

&lt;p&gt;Keys handle API-side limits. But we also need to prevent individual users from draining all keys:&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;// Simple IP-based rate limit&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateLimitMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isRateLimited&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&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;maxRequests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;windowMs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60000&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;now&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rateLimitMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;recent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;windowMs&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;recent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;maxRequests&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;rateLimitMap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&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;This gives each user 5 requests per minute — enough for genuine use, not enough to abuse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Free tiers are viable at scale&lt;/strong&gt; if you architect around their limits. Don't default to paid APIs until you've exhausted creative solutions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Round-robin beats random selection&lt;/strong&gt;. Random can hit the same key twice; round-robin guarantees even distribution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Always rotate after success too&lt;/strong&gt; — not just on failure. This prevents one key from handling 90% of traffic while others sit idle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor key usage&lt;/strong&gt;. We log which key handled each request. This tells us if one key is consistently rate-limited (meaning traffic exceeded capacity).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;All 4 AI tools are live and free at &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://freetoolforge.org/tools/text-tools/ai-summarizer" rel="noopener noreferrer"&gt;AI Text Summarizer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freetoolforge.org/tools/text-tools/ai-grammar-checker" rel="noopener noreferrer"&gt;AI Grammar Checker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freetoolforge.org/tools/text-tools/ai-paraphraser" rel="noopener noreferrer"&gt;AI Paraphraser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freetoolforge.org/tools/text-tools/ai-essay-writer" rel="noopener noreferrer"&gt;AI Essay Writer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each tool handles hundreds of daily users without a single paid API call.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://github.com/abidniazi" rel="noopener noreferrer"&gt;Abid Niazi&lt;/a&gt; — Full Stack Developer, Pakistan&lt;/em&gt;&lt;br&gt;
&lt;em&gt;ToolForge: &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt; — 61 free tools, no ads, no signup&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Built 56 Free Tools for Pakistani Students Using Next.js 14 — Architecture Deep Dive</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Mon, 18 May 2026 22:52:16 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/i-built-56-free-tools-for-pakistani-students-using-nextjs-14-architecture-deep-dive-50he</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/i-built-56-free-tools-for-pakistani-students-using-nextjs-14-architecture-deep-dive-50he</guid>
      <description>&lt;p&gt;Six months ago, I started building &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;ToolForge&lt;/a&gt; — a free online toolkit with 56+ tools for students, developers, and professionals.&lt;/p&gt;

&lt;p&gt;No ads. No signup. No data collection. Everything processes in the browser.&lt;/p&gt;

&lt;p&gt;Here's the technical deep dive into how it's built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14 App Router&lt;/strong&gt; — server components for SEO, client components for interactivity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; — caught hundreds of bugs before deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; — consistent dark theme across 56+ pages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini AI&lt;/strong&gt; — powers 4 AI tools via a custom key rotation system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — auto-deploy on push, free tier handles all traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Dual-URL Architecture
&lt;/h2&gt;

&lt;p&gt;Every tool gets TWO indexable URLs:&lt;br&gt;
/tools/calculators/emi-calculator    ← the interactive tool&lt;br&gt;
/emi-calculator                       ← long-form SEO guide page&lt;/p&gt;

&lt;p&gt;The tool page targets action keywords ("emi calculator"). The guide page targets informational keywords ("how to calculate emi in pakistan"). This doubled our indexed pages without duplicating content.&lt;/p&gt;
&lt;h2&gt;
  
  
  The AI Challenge: Free Tier Key Rotation
&lt;/h2&gt;

&lt;p&gt;We built 4 AI tools (Summarizer, Grammar Checker, Paraphraser, Essay Writer) using Google Gemini's free tier.&lt;/p&gt;

&lt;p&gt;The problem? 15 requests/minute per key.&lt;/p&gt;

&lt;p&gt;Our solution: round-robin rotation across 5 API keys with automatic failover on 429 errors.&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;// Simplified version of our key rotation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;KEY_1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;KEY_2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;KEY_3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;KEY_4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;KEY_5&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;currentIndex&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchWithKeyRotation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;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;attempts&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;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;attempts&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="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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GEMINI_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-goog-api-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;continue&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="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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentIndex&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;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="s1"&gt;All keys exhausted&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: 150,000 free API calls/month. Our AI tools are genuinely free to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pakistan-Specific Tools
&lt;/h2&gt;

&lt;p&gt;Instead of competing globally, we built tools nobody else has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MDCAT Aggregate Calculator&lt;/strong&gt; — medical college admission formula&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NUST/FAST/UET Merit Calculators&lt;/strong&gt; — university admission aggregates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FBR Income Tax Calculator&lt;/strong&gt; — Pakistan tax slabs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Electricity Bill Calculator&lt;/strong&gt; — NEPRA slab rates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zakat Calculator&lt;/strong&gt; — Islamic finance with PKR nisab values&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;University Comparator&lt;/strong&gt; — compare aggregate across 5 universities at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools have almost zero global competition but massive local demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO Results (3 Months)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Indexed pages&lt;/td&gt;
&lt;td&gt;86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Organic keywords&lt;/td&gt;
&lt;td&gt;82 (+1,071%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CTR&lt;/td&gt;
&lt;td&gt;12.1% (industry avg: 2-5%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total tools&lt;/td&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guides/blogs&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The high CTR tells us titles work. The average position (~23) tells us we need more backlinks. Hence this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Blogs drive more traffic than tools.&lt;/strong&gt; Our pillar guides (25-30 min reads) rank better than individual tool pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build for a niche first.&lt;/strong&gt; Pakistan-specific tools have zero competition. We rank for keywords no one else targets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key rotation makes free tiers viable.&lt;/strong&gt; Don't pay for APIs until you've exhausted free tier creatively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual URLs per tool = 2x indexed pages.&lt;/strong&gt; Simple architectural decision with massive SEO impact.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Everything is live and free at &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://freetoolforge.org/tools/text-tools/ai-essay-writer" rel="noopener noreferrer"&gt;AI Essay Writer&lt;/a&gt; and &lt;a href="https://freetoolforge.org/tools/calculators/university-compare" rel="noopener noreferrer"&gt;University Comparator&lt;/a&gt; are the most popular tools right now.&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the architecture in the comments.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://github.com/abidniazi" rel="noopener noreferrer"&gt;Abid Niazi&lt;/a&gt; — Full Stack Developer, Pakistan&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>I Built 56 Free Tools for Pakistani Students Using Next.js — Here's What I Learned</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Fri, 15 May 2026 11:43:35 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/i-built-56-free-tools-for-pakistani-students-using-nextjs-heres-what-i-learned-5glp</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/i-built-56-free-tools-for-pakistani-students-using-nextjs-heres-what-i-learned-5glp</guid>
      <description>

&lt;p&gt;Six months ago, I started building &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;ToolForge&lt;/a&gt; — a completely free online toolkit for students, developers, and professionals in Pakistan.&lt;/p&gt;

&lt;p&gt;Today it has &lt;strong&gt;56 tools&lt;/strong&gt;, 86 indexed pages on Google, and gets organic traffic from 15+ countries. No ads, no signup, no data collection.&lt;/p&gt;

&lt;p&gt;Here's the technical journey — what worked, what broke, and what I'd do differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14 App Router&lt;/strong&gt; — SSR for SEO, server components for speed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; — caught 200+ bugs before deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; — shipped UI 3x faster than custom CSS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; — auto-deploy on git push, free tier handles our traffic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemini API&lt;/strong&gt; — powers 4 AI tools (summarizer, grammar checker, paraphraser, essay writer)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture Decision: Why App Router?
&lt;/h2&gt;

&lt;p&gt;Every tool page needed to be independently indexable by Google. The App Router's file-based routing made this natural:&lt;br&gt;
src/app/tools/calculators/emi-calculator/page.tsx    ← tool&lt;br&gt;
src/app/emi-calculator/page.tsx                       ← SEO guide&lt;/p&gt;

&lt;p&gt;Each tool gets TWO URLs — the tool itself and a long-form guide page targeting different keywords. This doubled our indexable pages without doubling content.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Tools Challenge
&lt;/h2&gt;

&lt;p&gt;We built 4 AI-powered tools using Google's Gemini API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI Text Summarizer&lt;/li&gt;
&lt;li&gt;AI Grammar Checker
&lt;/li&gt;
&lt;li&gt;AI Paraphraser&lt;/li&gt;
&lt;li&gt;AI Essay Writer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The challenge? Rate limits. Gemini's free tier gives 15 requests/minute per key.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution: Key rotation system&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We rotate across 5 API keys with automatic failover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Round-robin selection&lt;/li&gt;
&lt;li&gt;Auto-switch on 429 (rate limit) errors
&lt;/li&gt;
&lt;li&gt;Capacity: 150,000 requests/month on free tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means our AI tools are genuinely free — no hidden costs passed to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO Results (Real Numbers)
&lt;/h2&gt;

&lt;p&gt;After 3 months:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;86 pages indexed by Google&lt;/li&gt;
&lt;li&gt;1,750 impressions, 244 clicks&lt;/li&gt;
&lt;li&gt;13.9% CTR (industry average is 2-5%)&lt;/li&gt;
&lt;li&gt;Average position: 20.9&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The high CTR tells me our titles and meta descriptions are working. The average position (page 2-3) tells me we need more backlinks and content depth to break into page 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pakistan-Specific Tools (Our Niche)
&lt;/h2&gt;

&lt;p&gt;Instead of competing with global tools, we built Pakistan-specific calculators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MDCAT Aggregate Calculator (medical college admissions)&lt;/li&gt;
&lt;li&gt;NUST/FAST/UET Merit Calculators (university admissions)&lt;/li&gt;
&lt;li&gt;FBR Income Tax Calculator&lt;/li&gt;
&lt;li&gt;Freelancer Tax Calculator (PSEB exemptions)&lt;/li&gt;
&lt;li&gt;Electricity Bill Calculator (NEPRA slab rates)&lt;/li&gt;
&lt;li&gt;Zakat Calculator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These have almost zero competition internationally but massive local demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd Do Differently
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with blogs, not tools&lt;/strong&gt; — Our pillar blog posts drive more traffic than individual tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build the sitemap correctly from day 1&lt;/strong&gt; — We had indexing issues from a misconfigured redirect&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus on 10 tools, not 56&lt;/strong&gt; — Better to have 10 perfect tools than 56 good ones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get backlinks early&lt;/strong&gt; — DA matters more than I thought for ranking speed&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The entire site is live at &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt;. Everything is free, no signup required.&lt;/p&gt;

&lt;p&gt;If you're building a tools site, I'm happy to share more details about the architecture in the comments.&lt;/p&gt;

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

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building Privacy-First Browser Tools: How ToolForge Processes PDFs Without a Server</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Thu, 14 May 2026 06:54:30 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/building-privacy-first-browser-tools-how-toolforge-processes-pdfs-without-a-server-1m3j</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/building-privacy-first-browser-tools-how-toolforge-processes-pdfs-without-a-server-1m3j</guid>
      <description>&lt;p&gt;Most "free" online PDF tools upload your files to their servers.&lt;br&gt;
That means your medical documents, salary slips, financial records,&lt;br&gt;
and confidential contracts are sitting on someone else's computer.&lt;/p&gt;

&lt;p&gt;When I built ToolForge's 12 PDF tools, I made a hard decision: &lt;strong&gt;nothing&lt;br&gt;
leaves the browser.&lt;/strong&gt; Here's exactly how I built it and what I learned.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why Browser-Only Matters
&lt;/h2&gt;

&lt;p&gt;When you compress a PDF on most free tools, here's what actually happens:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your file uploads to their AWS/Google Cloud bucket&lt;/li&gt;
&lt;li&gt;Server-side code processes it&lt;/li&gt;
&lt;li&gt;Processed file downloads back to you&lt;/li&gt;
&lt;li&gt;Your original file sits in their storage (usually deleted after 24h... usually)
For a salary slip, medical report, or legal document — this is a real
privacy risk. Browser-only processing eliminates it entirely.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  The Core Library: PDF.js + PDF-lib
&lt;/h2&gt;

&lt;p&gt;I use two libraries for different PDF operations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PDF.js&lt;/strong&gt; (Mozilla) — for reading and rendering PDFs&lt;br&gt;
&lt;strong&gt;PDF-lib&lt;/strong&gt; — for creating, modifying, and manipulating PDFs&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;pdfjs-dist pdf-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  PDF Compression (Client-Side)
&lt;/h2&gt;

&lt;p&gt;True compression requires re-encoding, which is complex client-side.&lt;br&gt;
My approach: re-render each PDF page to a canvas at slightly reduced&lt;br&gt;
quality, then rebuild the PDF from those images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pdfjsLib&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdfjs-dist&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;PDFDocument&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;compressPDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quality&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.7&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;arrayBuffer&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&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;pdf&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;pdfjsLib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;promise&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;newPdf&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;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numPages&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;page&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;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPage&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getViewport&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Render page to canvas&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canvas&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;canvas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&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;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;canvasContext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Convert canvas to JPEG (this is where compression happens)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;imageDataUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;canvas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;image/jpeg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;quality&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;imageBytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageDataUrl&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;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// Add to new PDF&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jpgImage&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;newPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;embedJpg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;imageBytes&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;newPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nx"&gt;newPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drawImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jpgImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;newPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&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;This achieves 40–70% file size reduction while keeping all pages intact.&lt;br&gt;
Everything runs in the user's browser — no upload required.&lt;/p&gt;


&lt;h2&gt;
  
  
  PDF Merging
&lt;/h2&gt;

&lt;p&gt;Merging is simpler — PDF-lib handles this natively:&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mergePDFs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&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;mergedPdf&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;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&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;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;files&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;arrayBuffer&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&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;pdf&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;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&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;pages&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;mergedPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copyPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPageIndices&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;mergedPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mergedPdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&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;Drop it in a &lt;code&gt;&amp;lt;input type="file" multiple accept=".pdf"&amp;gt;&lt;/code&gt;, call this&lt;br&gt;
function, and trigger a download. That's the entire merge tool.&lt;/p&gt;


&lt;h2&gt;
  
  
  PDF Rotation
&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;degrees&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pdf-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;rotatePDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&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;arrayBuffer&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&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;pdf&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;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&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;pages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPages&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentRotation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getRotation&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setRotation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;degrees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentRotation&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&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;
  
  
  Password Protection (Lock/Unlock PDF)
&lt;/h2&gt;

&lt;p&gt;PDF-lib supports encryption. For locking:&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;lockPDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&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;arrayBuffer&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&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;pdf&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;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// PDF-lib uses the standard PDF encryption spec&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfBytes&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;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;userPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ownerPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;_owner&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;printing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lowResolution&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;modifying&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;copying&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pdfBytes&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;For unlocking — you load the PDF with the user-provided password:&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;unlockPDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&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;arrayBuffer&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayBuffer&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;pdf&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;PDFDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Save without password&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&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;
  
  
  Handling Large Files
&lt;/h2&gt;

&lt;p&gt;The main challenge with browser-based PDF processing is memory.&lt;br&gt;
Large files (50MB+) can crash the browser tab. My solution:&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;// Check file size before processing&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MAX_SIZE_MB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;50&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;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;MAX_SIZE_MB&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`File too large. Maximum size is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;MAX_SIZE_MB&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;MB.`&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;}&lt;/span&gt;

&lt;span class="c1"&gt;// Process in chunks for multi-page documents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CHUNK_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// pages per chunk&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="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="nx"&gt;totalPages&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="nx"&gt;CHUNK_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;processPageChunk&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&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="nx"&gt;CHUNK_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="c1"&gt;// Small delay to prevent UI freeze&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&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;
  
  
  The Result: 12 PDF Tools, Zero Server Uploads
&lt;/h2&gt;

&lt;p&gt;ToolForge now has 12 browser-based PDF tools:&lt;br&gt;
Compress, Merge, Split, Rotate, Lock, Unlock, Watermark,&lt;br&gt;
Sign, PDF↔Word, PDF→JPG, PDF→Excel, Image→PDF.&lt;/p&gt;

&lt;p&gt;Every single one processes files locally. No data ever leaves your browser.&lt;/p&gt;

&lt;p&gt;The full toolkit is free at &lt;a href="https://freetoolforge.org/tools/document-tools" rel="noopener noreferrer"&gt;freetoolforge.org/tools/document-tools&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you built browser-based file processing tools? What was your biggest&lt;br&gt;
challenge? Drop it in the comments — I'd genuinely like to know.&lt;/p&gt;




&lt;p&gt;WORD COUNT: ~780 words&lt;br&gt;
ESTIMATED READ TIME: 5 min&lt;/p&gt;







</description>
      <category>javascript</category>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Built a Free CGPA, MDCAT &amp; Merit Calculator for Pakistani Students</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Thu, 14 May 2026 06:52:09 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/how-i-built-a-free-cgpa-mdcat-merit-calculator-for-pakistani-students-41kd</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/how-i-built-a-free-cgpa-mdcat-merit-calculator-for-pakistani-students-41kd</guid>
      <description>&lt;p&gt;Pakistani students get ignored by most tools on the internet.&lt;/p&gt;

&lt;p&gt;Every CGPA calculator uses the US 4.0 grading scale. Every merit calculator&lt;br&gt;
doesn't know what NUST or FAST or MDCAT is. Every EMI calculator shows&lt;br&gt;
interest rates in USD.&lt;/p&gt;

&lt;p&gt;So I built ToolForge — a free toolkit specifically for Pakistan. Here's what&lt;br&gt;
I learned building three of its most-used calculators.&lt;/p&gt;


&lt;h2&gt;
  
  
  The CGPA Calculator Problem
&lt;/h2&gt;

&lt;p&gt;Pakistan's Higher Education Commission (HEC) uses a grading scale that's&lt;br&gt;
subtly different from the US system most calculators are built on.&lt;/p&gt;

&lt;p&gt;The key difference: in Pakistan, both A and A+ map to 4.0 grade points.&lt;br&gt;
In the US, A+ is sometimes 4.3. This sounds minor but it causes significant&lt;br&gt;
errors when students use US-based calculators for Pakistani universities.&lt;/p&gt;

&lt;p&gt;Here's the HEC scale:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A+ = 4.0  (90–100%)
A  = 4.0  (85–89%)
A- = 3.7  (80–84%)
B+ = 3.3  (75–79%)
B  = 3.0  (70–74%)
B- = 2.7  (65–69%)
C+ = 2.3  (60–64%)
C  = 2.0  (55–59%)
F  = 0.0  (below 50%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CGPA formula itself is straightforward:&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;calculateCGPA&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subjects&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;totalWeightedPoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gradePoints&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;creditHours&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;totalCreditHours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;subjects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;creditHours&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;totalWeightedPoints&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;totalCreditHours&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tricky part was building the UI to dynamically add/remove subjects&lt;br&gt;
while keeping the calculation reactive. I used React state with an array&lt;br&gt;
of subject objects:&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;subjects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setSubjects&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&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="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="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;grade&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="na"&gt;creditHours&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try the live calculator: &lt;a href="https://freetoolforge.org/tools/calculators/gpa-calculator" rel="noopener noreferrer"&gt;freetoolforge.org/tools/calculators/gpa-calculator&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The MDCAT Aggregate Calculator
&lt;/h2&gt;

&lt;p&gt;MDCAT (Medical and Dental College Admission Test) uses a specific formula&lt;br&gt;
that most calculators get wrong:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MDCAT Merit = (Matric % × 10%) + (FSc % × 40%) + (MDCAT Score × 50%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different universities then apply their own cutoffs on top of this aggregate.&lt;br&gt;
I built a version that calculates the standard PMC formula and shows you&lt;br&gt;
which universities you're likely eligible for based on last year's cutoffs.&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;calculateMDCATAggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fsc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mdcatScore&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;matricWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matric&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&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;fscWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fsc&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;40&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;mdcatWeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mdcatScore&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matricWeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;fscWeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;mdcatWeight&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Live tool: &lt;a href="https://freetoolforge.org/tools/calculators/mdcat-aggregate-calculator" rel="noopener noreferrer"&gt;freetoolforge.org/tools/calculators/mdcat-aggregate-calculator&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Merit Calculator Challenge
&lt;/h2&gt;

&lt;p&gt;The Merit Calculator was the hardest to build — not because of the math,&lt;br&gt;
but because every Pakistani university has a different formula:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NUST: Entry test 75% + FSc 15% + Matric 10%&lt;/li&gt;
&lt;li&gt;FAST: Their own aptitude test with its own weighting&lt;/li&gt;
&lt;li&gt;UET Lahore: Matric + FSc + UET entry test&lt;/li&gt;
&lt;li&gt;LUMS: SAT-based, entirely different system
I ended up building it with a dropdown to select the university, then
dynamically rendering the correct formula and input fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key technical decision: I stored all university formulas in a config&lt;br&gt;
object rather than hardcoding them, so adding a new university is just&lt;br&gt;
adding an object entry:&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;UNIVERSITY_FORMULAS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;NUST&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NUST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;formula&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fsc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entryTest&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;matric&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fsc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entryTest&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.75&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matric %&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;FSc %&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;NET Score (out of 200)&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;UET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UET Lahore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;formula&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;matric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fsc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entryTest&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;matric&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fsc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entryTest&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matric %&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;FSc %&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;UET Entry Test %&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ... more universities&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Live tool: &lt;a href="https://freetoolforge.org/tools/calculators/merit-calculator" rel="noopener noreferrer"&gt;freetoolforge.org/tools/calculators/merit-calculator&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned Building Pakistan-Specific Tools
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Context is everything.&lt;/strong&gt;&lt;br&gt;
A generic calculator is useless to a Pakistani student. Pakistan has its own&lt;br&gt;
grading scales, tax slabs, bank rates, and admission formulas. Building&lt;br&gt;
for a specific context — even a smaller audience — gives you users who&lt;br&gt;
are deeply engaged because the tool actually works for their situation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Privacy matters more than people admit.&lt;/strong&gt;&lt;br&gt;
All ToolForge calculations happen in the browser. No data is sent to any&lt;br&gt;
server. Users don't have to worry about their salary, CGPA, or tax info&lt;br&gt;
being stored anywhere. This was a deliberate design choice and users&lt;br&gt;
genuinely appreciate it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. SEO for specific audiences is easier.&lt;/strong&gt;&lt;br&gt;
"CGPA calculator" is a competitive keyword globally. "CGPA calculator&lt;br&gt;
Pakistan HEC scale" is almost entirely uncontested. Building for a specific&lt;br&gt;
audience means you rank faster with less effort.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 14&lt;/strong&gt; App Router with TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS&lt;/strong&gt; for all styling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel&lt;/strong&gt; for deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemini API&lt;/strong&gt; for AI-powered tools (with key rotation)&lt;/li&gt;
&lt;li&gt;All calculations run client-side — zero database
The full toolkit is live at &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;freetoolforge.org&lt;/a&gt; —
50+ free tools, no signup, no ads. I'd love feedback from Pakistani
developers and students on what to build next.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What country-specific tools have you built or wished existed?&lt;/p&gt;




&lt;p&gt;WORD COUNT: ~820 words&lt;br&gt;
ESTIMATED READ TIME: 5 min&lt;/p&gt;







</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Ultimate Free Productivity Toolkit for Students in 2026</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Fri, 08 May 2026 18:02:27 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/the-ultimate-free-productivity-toolkit-for-students-in-2026-1dgd</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/the-ultimate-free-productivity-toolkit-for-students-in-2026-1dgd</guid>
      <description>&lt;p&gt;University students today handle much more than classes.&lt;/p&gt;

&lt;p&gt;Assignments.&lt;br&gt;
Presentations.&lt;br&gt;
PDF submissions.&lt;br&gt;
Internships.&lt;br&gt;
Freelancing.&lt;br&gt;
Online learning.&lt;br&gt;
CV building.&lt;br&gt;
Research work.&lt;/p&gt;

&lt;p&gt;The problem is that students constantly switch between dozens of websites just to complete small tasks.&lt;/p&gt;

&lt;p&gt;One tool for GPA calculation.&lt;br&gt;
Another for PDF compression.&lt;br&gt;
Another for grammar correction.&lt;br&gt;
Another for word counting.&lt;/p&gt;

&lt;p&gt;Recently, I explored a browser-based platform called ToolForge, and it surprisingly combines many useful student productivity tools in one place.&lt;/p&gt;

&lt;p&gt;Here are the tools I think students should bookmark in 2026.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. GPA Calculator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/calculators/gpa-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/gpa-calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably one of the most useful tools for university students.&lt;/p&gt;

&lt;p&gt;Instead of calculating GPA manually, this tool helps students quickly estimate semester performance.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Semester GPA calculation&lt;/li&gt;
&lt;li&gt;Credit hour tracking&lt;/li&gt;
&lt;li&gt;Academic planning&lt;/li&gt;
&lt;li&gt;Scholarship eligibility&lt;/li&gt;
&lt;li&gt;Performance analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple tool, but students use it constantly throughout university life.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. CGPA to Percentage Calculator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/calculators/cgpa-to-percentage" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/cgpa-to-percentage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is especially valuable for Pakistani students.&lt;/p&gt;

&lt;p&gt;Many universities, internships, and companies still require percentage-based grading systems.&lt;/p&gt;

&lt;p&gt;The tool instantly converts CGPA into percentage format for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job applications&lt;/li&gt;
&lt;li&gt;University admissions&lt;/li&gt;
&lt;li&gt;Scholarship forms&lt;/li&gt;
&lt;li&gt;Internship applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Very practical and saves time.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. PDF Compressor
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/document-tools/pdf-compressor" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/document-tools/pdf-compressor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every student eventually faces the same problem:&lt;/p&gt;

&lt;p&gt;“File size exceeds upload limit.”&lt;/p&gt;

&lt;p&gt;This tool helps compress PDF files quickly without needing complicated desktop software.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assignment submissions&lt;/li&gt;
&lt;li&gt;Research papers&lt;/li&gt;
&lt;li&gt;Thesis uploads&lt;/li&gt;
&lt;li&gt;Resume uploads&lt;/li&gt;
&lt;li&gt;Government applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A genuine lifesaver during deadlines.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. AI Grammar Checker
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/text-tools/ai-grammar-checker" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/text-tools/ai-grammar-checker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good communication matters more than most students realize.&lt;/p&gt;

&lt;p&gt;Whether you're writing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assignments&lt;/li&gt;
&lt;li&gt;Emails&lt;/li&gt;
&lt;li&gt;LinkedIn posts&lt;/li&gt;
&lt;li&gt;CVs&lt;/li&gt;
&lt;li&gt;Reports&lt;/li&gt;
&lt;li&gt;Freelance proposals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grammar quality affects professionalism.&lt;/p&gt;

&lt;p&gt;This AI Grammar Checker helps improve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sentence clarity&lt;/li&gt;
&lt;li&gt;Grammar mistakes&lt;/li&gt;
&lt;li&gt;Writing flow&lt;/li&gt;
&lt;li&gt;Readability&lt;/li&gt;
&lt;li&gt;Professional tone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Extremely useful for students preparing for internships and remote work opportunities.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Word Counter
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/text-tools/word-counter" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/text-tools/word-counter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A surprisingly important productivity tool.&lt;/p&gt;

&lt;p&gt;Most universities have strict word count requirements for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Essays&lt;/li&gt;
&lt;li&gt;Reports&lt;/li&gt;
&lt;li&gt;Research papers&lt;/li&gt;
&lt;li&gt;Summaries&lt;/li&gt;
&lt;li&gt;Assignments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This tool helps track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Word count&lt;/li&gt;
&lt;li&gt;Character count&lt;/li&gt;
&lt;li&gt;Reading time&lt;/li&gt;
&lt;li&gt;Writing statistics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple but essential.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Image Compressor
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/image-tools/image-compressor" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/image-tools/image-compressor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Students constantly upload images for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portfolios&lt;/li&gt;
&lt;li&gt;Assignments&lt;/li&gt;
&lt;li&gt;CVs&lt;/li&gt;
&lt;li&gt;Project documentation&lt;/li&gt;
&lt;li&gt;Freelance profiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compressed images help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce upload size&lt;/li&gt;
&lt;li&gt;Improve website speed&lt;/li&gt;
&lt;li&gt;Save storage&lt;/li&gt;
&lt;li&gt;Improve SEO for portfolios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially useful for students learning web development and e-commerce.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. QR Code Generator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/qr-code-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/qr-code-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A very underrated student tool.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portfolio sharing&lt;/li&gt;
&lt;li&gt;Event registration&lt;/li&gt;
&lt;li&gt;Resume links&lt;/li&gt;
&lt;li&gt;GitHub projects&lt;/li&gt;
&lt;li&gt;Google Drive sharing&lt;/li&gt;
&lt;li&gt;Presentation links&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Students can instantly create QR codes for digital projects and presentations.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Password Generator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/password-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/password-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Students manage multiple accounts daily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;University portals&lt;/li&gt;
&lt;li&gt;LMS dashboards&lt;/li&gt;
&lt;li&gt;Freelance platforms&lt;/li&gt;
&lt;li&gt;GitHub&lt;/li&gt;
&lt;li&gt;Email accounts&lt;/li&gt;
&lt;li&gt;Banking apps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using weak passwords is risky.&lt;/p&gt;

&lt;p&gt;This tool helps generate secure passwords quickly and safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Online Compiler
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/online-compiler" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/online-compiler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A great tool for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CS students&lt;/li&gt;
&lt;li&gt;Programming beginners&lt;/li&gt;
&lt;li&gt;Quick debugging&lt;/li&gt;
&lt;li&gt;Coding practice&lt;/li&gt;
&lt;li&gt;Interview preparation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of setting up heavy local environments, students can quickly test snippets directly in the browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Browser-Based Productivity Tools Are Growing Fast
&lt;/h2&gt;

&lt;p&gt;Students today value speed and convenience.&lt;/p&gt;

&lt;p&gt;The biggest advantages are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No installation required&lt;/li&gt;
&lt;li&gt;Mobile friendly&lt;/li&gt;
&lt;li&gt;Free access&lt;/li&gt;
&lt;li&gt;Fast workflow&lt;/li&gt;
&lt;li&gt;Easy to use&lt;/li&gt;
&lt;li&gt;Works anywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of bookmarking 20 different websites, platforms like ToolForge combine everything into one clean productivity ecosystem.&lt;/p&gt;

&lt;p&gt;For students balancing academics, internships, freelancing, and online learning, these small tools genuinely save time every week.&lt;/p&gt;

&lt;p&gt;Main website:&lt;br&gt;
🔗 &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;https://freetoolforge.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What productivity tools do you use most frequently as a student?&lt;/p&gt;

</description>
    </item>
    <item>
      <title>9 Free Developer Tools That Save Me Hours Every Week</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Fri, 08 May 2026 17:57:24 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/9-free-developer-tools-that-save-me-hours-every-week-46gf</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/9-free-developer-tools-that-save-me-hours-every-week-46gf</guid>
      <description>&lt;p&gt;As developers, we spend a surprising amount of time on small repetitive tasks.&lt;/p&gt;

&lt;p&gt;Formatting JSON.&lt;br&gt;
Generating secure passwords.&lt;br&gt;
Creating QR codes.&lt;br&gt;
Testing quick snippets.&lt;br&gt;
Generating UUIDs.&lt;/p&gt;

&lt;p&gt;Individually, these tasks seem tiny. But together they can easily waste hours every week if you constantly jump between random websites and desktop apps.&lt;/p&gt;

&lt;p&gt;Recently, I started using a browser-based toolkit called ToolForge, and it simplified a lot of my daily workflow.&lt;/p&gt;

&lt;p&gt;Here are the developer tools I genuinely found useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. JSON Formatter
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/text-tools/json-formatter" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/text-tools/json-formatter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you work with APIs, this tool becomes essential very quickly.&lt;/p&gt;

&lt;p&gt;Instead of reading messy API responses, the JSON Formatter instantly converts raw JSON into clean, readable, structured data.&lt;/p&gt;

&lt;p&gt;I mostly use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API debugging&lt;/li&gt;
&lt;li&gt;Backend testing&lt;/li&gt;
&lt;li&gt;Frontend integration&lt;/li&gt;
&lt;li&gt;Nested object validation&lt;/li&gt;
&lt;li&gt;Learning API structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For developers working with REST APIs daily, this saves a lot of time.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. QR Code Generator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/qr-code-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/qr-code-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is one of those tools you don’t think about until you need it constantly.&lt;/p&gt;

&lt;p&gt;I’ve used it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portfolio links&lt;/li&gt;
&lt;li&gt;GitHub repositories&lt;/li&gt;
&lt;li&gt;WiFi sharing&lt;/li&gt;
&lt;li&gt;Mobile testing&lt;/li&gt;
&lt;li&gt;Event registration pages&lt;/li&gt;
&lt;li&gt;App download links&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tool is lightweight, fast, and generates clean QR codes instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Password Generator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/password-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/password-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Managing multiple environments and dashboards means developers need strong passwords constantly.&lt;/p&gt;

&lt;p&gt;This tool helps generate highly secure passwords with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uppercase characters&lt;/li&gt;
&lt;li&gt;Lowercase characters&lt;/li&gt;
&lt;li&gt;Numbers&lt;/li&gt;
&lt;li&gt;Symbols&lt;/li&gt;
&lt;li&gt;Custom password lengths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin dashboards&lt;/li&gt;
&lt;li&gt;Hosting panels&lt;/li&gt;
&lt;li&gt;Database credentials&lt;/li&gt;
&lt;li&gt;Team accounts&lt;/li&gt;
&lt;li&gt;Deployment platforms&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  4. UUID Generator
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/uuid-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/uuid-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A simple but extremely practical utility.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database IDs&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Backend development&lt;/li&gt;
&lt;li&gt;Mock API data&lt;/li&gt;
&lt;li&gt;Session identifiers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the smallest tools end up being the most frequently used.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Online Compiler
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/online-compiler" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/online-compiler&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are moments when you just want to test a quick snippet without opening your full local setup.&lt;/p&gt;

&lt;p&gt;This browser compiler is helpful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Students&lt;/li&gt;
&lt;li&gt;Beginners&lt;/li&gt;
&lt;li&gt;Quick debugging&lt;/li&gt;
&lt;li&gt;Interview preparation&lt;/li&gt;
&lt;li&gt;Learning programming languages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fast and convenient.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Base64 Encoder
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/base64-encoder" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/base64-encoder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful when working with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication systems&lt;/li&gt;
&lt;li&gt;Tokens&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;Encoded assets&lt;/li&gt;
&lt;li&gt;Data transfer testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A very practical developer utility.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. IP Address Lookup
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/ip-lookup" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/ip-lookup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Helpful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network debugging&lt;/li&gt;
&lt;li&gt;Security checks&lt;/li&gt;
&lt;li&gt;VPN verification&lt;/li&gt;
&lt;li&gt;Location testing&lt;/li&gt;
&lt;li&gt;Hosting diagnostics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Especially useful for developers working with deployment and server configurations.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Color Picker
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/developer-tools/color-picker" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/developer-tools/color-picker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Frontend developers and designers will probably use this a lot.&lt;/p&gt;

&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UI design&lt;/li&gt;
&lt;li&gt;Branding&lt;/li&gt;
&lt;li&gt;CSS development&lt;/li&gt;
&lt;li&gt;Tailwind projects&lt;/li&gt;
&lt;li&gt;Theme customization&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Markdown Editor
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://freetoolforge.org/tools/text-tools/markdown-editor" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/text-tools/markdown-editor&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A clean browser-based editor for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;README files&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Technical blogs&lt;/li&gt;
&lt;li&gt;Notes&lt;/li&gt;
&lt;li&gt;GitHub content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Very useful if you write developer documentation frequently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Like Browser-Based Developer Tools
&lt;/h2&gt;

&lt;p&gt;The biggest advantage is convenience.&lt;/p&gt;

&lt;p&gt;No installations.&lt;br&gt;
No unnecessary signups.&lt;br&gt;
No storage issues.&lt;br&gt;
No switching between dozens of websites.&lt;/p&gt;

&lt;p&gt;Everything works directly inside the browser.&lt;/p&gt;

&lt;p&gt;For developers, students, and freelancers, having multiple utilities in one place genuinely improves workflow and productivity.&lt;/p&gt;

&lt;p&gt;Main website:&lt;br&gt;
🔗 &lt;a href="https://freetoolforge.org" rel="noopener noreferrer"&gt;https://freetoolforge.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Would love to know what developer tools you use most frequently in your daily workflow.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why Simple Tools Get More Traffic Than Complex Apps</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Wed, 06 May 2026 19:41:16 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/why-simple-tools-get-more-traffic-than-complex-apps-15ki</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/why-simple-tools-get-more-traffic-than-complex-apps-15ki</guid>
      <description>&lt;p&gt;Users don’t want complexity.&lt;/p&gt;

&lt;p&gt;They want solutions.&lt;/p&gt;

&lt;p&gt;That’s why tools like:&lt;/p&gt;

&lt;p&gt;MDCAT Calculator&lt;br&gt;
&lt;a href="https://freetoolforge.org/tools/calculators/mdcat-aggregate-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/mdcat-aggregate-calculator&lt;/a&gt;&lt;br&gt;
Vehicle Tax Calculator&lt;br&gt;
&lt;a href="https://freetoolforge.org/tools/calculators/vehicle-token-tax-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/vehicle-token-tax-calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;perform better.&lt;/p&gt;

&lt;p&gt;👉 They solve one problem instantly.&lt;/p&gt;

&lt;p&gt;Explore all tools: &lt;a href="https://freetoolforge.org/" rel="noopener noreferrer"&gt;https://freetoolforge.org/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>programming</category>
      <category>productivity</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built Simple Calculators That Solve Real Problems</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Wed, 06 May 2026 19:39:37 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/i-built-simple-calculators-that-solve-real-problems-3cd1</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/i-built-simple-calculators-that-solve-real-problems-3cd1</guid>
      <description>&lt;p&gt;Instead of building complex SaaS apps, I focused on solving small problems.&lt;/p&gt;

&lt;p&gt;Here are some tools:&lt;/p&gt;

&lt;p&gt;Tax Calculator&lt;br&gt;
&lt;a href="https://freetoolforge.org/tools/calculators/fbr-tax-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/fbr-tax-calculator&lt;/a&gt;&lt;br&gt;
Merit Calculator&lt;br&gt;
&lt;a href="https://freetoolforge.org/tools/calculators/merit-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/merit-calculator&lt;/a&gt;&lt;br&gt;
CGPA Converter&lt;br&gt;
&lt;a href="https://freetoolforge.org/tools/calculators/cgpa-to-percentage" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/cgpa-to-percentage&lt;/a&gt;&lt;br&gt;
Salary Slip Generator&lt;br&gt;
&lt;a href="https://freetoolforge.org/tools/calculators/salary-slip-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/salary-slip-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;👉 Lesson: small tools + real problems = real traffic&lt;/p&gt;

&lt;p&gt;Explore: &lt;a href="https://freetoolforge.org/" rel="noopener noreferrer"&gt;https://freetoolforge.org/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Built Free Calculators for Students &amp; Professionals — Here’s What Solved Real Problems</title>
      <dc:creator>Abid niazi</dc:creator>
      <pubDate>Mon, 04 May 2026 18:32:03 +0000</pubDate>
      <link>https://dev.to/abid_niazi_a7faa6246a7952/i-built-free-calculators-for-students-professionals-heres-what-solved-real-problems-co1</link>
      <guid>https://dev.to/abid_niazi_a7faa6246a7952/i-built-free-calculators-for-students-professionals-heres-what-solved-real-problems-co1</guid>
      <description>&lt;p&gt;Developers often build complex apps.&lt;br&gt;
I did the opposite.&lt;/p&gt;

&lt;p&gt;I built simple tools that solve real problems.&lt;/p&gt;

&lt;p&gt;Here are a few:&lt;/p&gt;

&lt;p&gt;💰 Tax Calculator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freetoolforge.org/tools/calculators/fbr-tax-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/fbr-tax-calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Helps users calculate tax instantly using FBR slabs.&lt;/p&gt;

&lt;p&gt;🎓 MDCAT Aggregate Calculator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freetoolforge.org/tools/calculators/mdcat-aggregate-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/mdcat-aggregate-calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Students can check admission chances in seconds.&lt;/p&gt;

&lt;p&gt;🏫 Merit Calculator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freetoolforge.org/tools/calculators/merit-calculator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/merit-calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quick admission merit calculation.&lt;/p&gt;

&lt;p&gt;📊 CGPA to Percentage&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freetoolforge.org/tools/calculators/cgpa-to-percentage" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/cgpa-to-percentage&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Converts GPA accurately.&lt;/p&gt;

&lt;p&gt;💼 Salary Slip Generator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://freetoolforge.org/tools/calculators/salary-slip-generator" rel="noopener noreferrer"&gt;https://freetoolforge.org/tools/calculators/salary-slip-generator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creates professional payslips instantly.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkel703zvlqesb2cq6bep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkel703zvlqesb2cq6bep.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4e9me0a64chovdop5eqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4e9me0a64chovdop5eqa.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzp99t9dsetmc3l66jfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzp99t9dsetmc3l66jfy.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwx98saj3ouv5z0zjbkw4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwx98saj3ouv5z0zjbkw4.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatos6jmi7ejy2ahvj1db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatos6jmi7ejy2ahvj1db.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
