<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gaurav Kalal</title>
    <description>The latest articles on Forem by Gaurav Kalal (@gorupa).</description>
    <link>https://forem.com/gorupa</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%2F3823842%2F61b568f7-591d-4992-aee6-988b3849d35b.jpg</url>
      <title>Forem: Gaurav Kalal</title>
      <link>https://forem.com/gorupa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gorupa"/>
    <language>en</language>
    <item>
      <title>💥 I Was Tired of Boring UIs, So I Built a CSS Framework Straight Out of a 1962 Comic Book</title>
      <dc:creator>Gaurav Kalal</dc:creator>
      <pubDate>Sun, 29 Mar 2026 11:36:34 +0000</pubDate>
      <link>https://forem.com/gorupa/i-was-tired-of-boring-uis-so-i-built-a-css-framework-straight-out-of-a-1962-comic-book-mc1</link>
      <guid>https://forem.com/gorupa/i-was-tired-of-boring-uis-so-i-built-a-css-framework-straight-out-of-a-1962-comic-book-mc1</guid>
      <description>&lt;p&gt;Let me ask you something.&lt;/p&gt;

&lt;p&gt;When was the last time you visited a website and thought &lt;em&gt;"wow, this UI has a personality"&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Be honest. Because I've been building on the web for years, and lately every project I open in Figma — or every starter template I pull from npm — looks identical. A sterile off-white background. Inter font at &lt;code&gt;font-weight: 400&lt;/code&gt;. A primary color from a muted blue palette that some product manager once called "trustworthy." A card with &lt;code&gt;border-radius: 8px&lt;/code&gt; and a whisper of a &lt;code&gt;box-shadow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's safe. It's clean. It's &lt;em&gt;everywhere.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And I am absolutely exhausted by it.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎨 The Web Used to Have Soul
&lt;/h2&gt;

&lt;p&gt;There was a time when websites were weird. Aggressively, unapologetically weird. Colors screamed at you. Borders were thick and black like someone drew them with a Sharpie. Things were &lt;em&gt;misaligned&lt;/em&gt; in ways that somehow felt intentional and full of energy.&lt;/p&gt;

&lt;p&gt;That visual language had a name: it lived in vintage comic books, in Roy Lichtenstein pop art, in the chunky, ink-heavy print design of the 50s, 60s, and yes — even the gloriously chaotic 90s.&lt;/p&gt;

&lt;p&gt;So I asked myself: &lt;em&gt;what if I just… brought that back?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not as a joke. Not as a gimmick. But as a real, usable CSS design system that any developer could drop into a project and instantly make something that felt alive.&lt;/p&gt;

&lt;p&gt;That's how &lt;strong&gt;KABOOM! UI&lt;/strong&gt; was born. 💥&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What is KABOOM! UI?
&lt;/h2&gt;

&lt;p&gt;KABOOM! UI is a &lt;strong&gt;100% pure CSS, zero-dependency design system&lt;/strong&gt; built to replicate the aesthetic of vintage comic books, Pop Art, and 90s nostalgia.&lt;/p&gt;

&lt;p&gt;There is no JavaScript. No build step. No npm install. You download one &lt;code&gt;.css&lt;/code&gt; file, drop a &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; tag in your &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;, and you're immediately writing UI that looks like it was printed on a comic book press.&lt;/p&gt;

&lt;p&gt;Heavy ink borders. Misaligned CMYK print shadows. Halftone dot backgrounds. Hand-drawn wobbly aesthetics. It's all in there, and it weighs almost nothing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🎨 &lt;strong&gt;&lt;a href="https://kaboom-ui-kit.pages.dev/" rel="noopener noreferrer"&gt;See the live demo → kaboom-ui-kit.pages.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;&lt;a href="https://github.com/Gorupa/kaboom-ui-kit" rel="noopener noreferrer"&gt;GitHub Repo → github.com/Gorupa/kaboom-ui-kit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Go check out the demo. I'll wait. I genuinely think it'll make you smile.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ The CSS Tricks That Make It Work
&lt;/h2&gt;

&lt;p&gt;Okay, here's the part I'm most excited to share — because building this thing taught me that you can achieve &lt;em&gt;a lot&lt;/em&gt; of personality with very basic CSS primitives. Let me walk you through two of my favorite techniques.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. 🔵 Halftone Dot Backgrounds with &lt;code&gt;radial-gradient&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you've ever looked closely at a printed comic book, you'll notice the backgrounds and shading aren't solid colors — they're made up of tiny dots. This is called the &lt;strong&gt;Ben-Day dot process&lt;/strong&gt;, and it's pure visual gold.&lt;/p&gt;

&lt;p&gt;Here's the thing: you don't need SVGs, images, or a canvas element to fake it. You can do it entirely with CSS using &lt;code&gt;radial-gradient&lt;/code&gt; inside &lt;code&gt;background-image&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.k-halftone&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;radial-gradient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="m"&gt;1.5px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;transparent&lt;/span&gt; &lt;span class="m"&gt;1.5px&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;10px&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;What's happening here? The &lt;code&gt;radial-gradient&lt;/code&gt; draws a tiny filled circle (&lt;code&gt;1.5px&lt;/code&gt; radius, solid black) at the center of each tile, and then fades to transparent for the rest of the space. The &lt;code&gt;background-size&lt;/code&gt; controls how far apart the dots are. Make the tile smaller and the dots get denser. Make the dot radius larger and you get that bold, chunky comic book look.&lt;/p&gt;

&lt;p&gt;Tweak the dot color, tile size, and radius, and you can create everything from a subtle texture to a screaming pop-art background. No images, no JavaScript, no dependencies — just math and gradients. 🎨&lt;/p&gt;




&lt;h3&gt;
  
  
  2. 🟡 Misaligned Print Shadows with &lt;code&gt;box-shadow&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is my personal favourite trick in the whole framework. If you look at cheaply printed comic books from the 60s, you'll notice that the color plates didn't always line up perfectly with the black ink outlines. This created a &lt;em&gt;gorgeous&lt;/em&gt; off-register shadow effect — a halo of cyan or magenta peeking out from behind the black border.&lt;/p&gt;

&lt;p&gt;You can fake this almost perfectly with a solid, no-blur &lt;code&gt;box-shadow&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.k-card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;#000&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 key here is &lt;code&gt;blur-radius: 0&lt;/code&gt;. A standard drop shadow uses blur to create a soft, realistic fade. But set it to zero and the shadow becomes a solid, hard-edged duplicate of your element — offset a few pixels down and to the right. It looks exactly like a second printing plate that didn't quite line up.&lt;/p&gt;

&lt;p&gt;Want to push it even further into "cheap print" territory? Stack multiple shadows and use CMYK-inspired colors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.k-card--pop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;#00bcd4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c"&gt;/* cyan plate — slightly offset */&lt;/span&gt;
    &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;7px&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c"&gt;/* black plate — the outermost shadow */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your element looks like it was legitimately pulled from a Roy Lichtenstein print. For zero lines of JavaScript. 💥&lt;/p&gt;




&lt;h2&gt;
  
  
  ✍️ How Easy Is It to Actually Use?
&lt;/h2&gt;

&lt;p&gt;This was a core design goal: getting from zero to comic-book in under 60 seconds. Here's all you need:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Link the stylesheet&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"comic-ui.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — Use the classes&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- A comic-book style card --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-card__badge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;HOT TAKE #7&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-card__title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Flat Design Is Overrated&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-card__body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    I said what I said. Give me ink borders or give me death.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-btn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Fight Me →&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- A halftone hero section --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-halftone"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-splash-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;POW!&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;No npm install required. Incredible.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"k-btn k-btn--danger"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;KABOOM!&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. No configuration. No theme tokens to set up. No &lt;code&gt;tailwind.config.js&lt;/code&gt;. Just classes that do exactly what they sound like.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Go Build Something Weird
&lt;/h2&gt;

&lt;p&gt;Here's the deal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Free "Sidekick" Tier&lt;/strong&gt; is fully open-sourced on GitHub right now. It includes the core components — buttons, cards, badges, speech bubbles, halftone backgrounds, and the full ink border and offset shadow system. Everything you need to build something that turns heads.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/Gorupa/kaboom-ui-kit" rel="noopener noreferrer"&gt;Grab it on GitHub → github.com/Gorupa/kaboom-ui-kit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to go deeper, there's also a &lt;strong&gt;Premium "Superhero" Tier&lt;/strong&gt; available on the demo site. It unlocks 50+ components, ready-to-use full HTML page templates (landing pages, pricing pages, portfolios), and the Figma source files — for the designers in the room who want to prototype with the same energy.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://kaboom-ui-kit.pages.dev/" rel="noopener noreferrer"&gt;Check out the full demo → kaboom-ui-kit.pages.dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 Now I Want to Hear From You
&lt;/h2&gt;

&lt;p&gt;I built KABOOM! UI because I genuinely believe the web gets more interesting when we stop optimizing purely for "professional" and start leaving a little room for &lt;em&gt;fun&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A few things I'd love your feedback on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;What components should I build next?&lt;/strong&gt; Speech bubbles? Comic-strip grid layouts? A villain-red alert banner? Drop your ideas in the comments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Does the aesthetic resonate?&lt;/strong&gt; Are there other nostalgic design eras you'd love to see explored in CSS?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Any CSS tricks you'd add?&lt;/strong&gt; I'm always looking to learn — if you've got a cool technique that fits the vibe, share it below.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if the halftone dots and ink borders put a smile on your face — even a small one — it would genuinely mean the world if you dropped a ⭐ on the &lt;a href="https://github.com/Gorupa/kaboom-ui-kit" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;. It helps other developers find it, and it lets me know this weird little project is worth continuing.&lt;/p&gt;

&lt;p&gt;Now go make something that doesn't look like every other website on the internet. 🥊&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Happy to answer any questions about the CSS techniques used or the design decisions behind the framework. Ask me anything in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a zero-dependency validation library for every Indian developer</title>
      <dc:creator>Gaurav Kalal</dc:creator>
      <pubDate>Sun, 15 Mar 2026 03:28:12 +0000</pubDate>
      <link>https://forem.com/gorupa/i-built-a-zero-dependency-validation-library-for-every-indian-developer-55ck</link>
      <guid>https://forem.com/gorupa/i-built-a-zero-dependency-validation-library-for-every-indian-developer-55ck</guid>
      <description>&lt;p&gt;Indian developer building a form has hit the same wall.&lt;/p&gt;

&lt;p&gt;You need to validate a PAN number. Or an Aadhaar. Or a GSTIN. Or an IFSC code. So you Google it, find a Stack Overflow answer from 2016, copy a regex, and hope it works.&lt;/p&gt;

&lt;p&gt;There was no clean, trustworthy, zero-dependency JavaScript library that handled all of this in one place.&lt;/p&gt;

&lt;p&gt;So I built one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing india-validators
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;india-validators&lt;/strong&gt; is a client-side JavaScript library that validates 9 common Indian document and identifier formats — with proper checksums, not just regex.&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;india-validators
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or drop it in directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/india-validators/india-validators.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No backend. No API calls. No data sent anywhere. Everything runs in the browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it validates
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Validator&lt;/th&gt;
&lt;th&gt;What it checks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aadhaar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12-digit format + Verhoeff checksum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10-char format + entity type decode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gstin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;15-char format + state code + mod-36 checksum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ifsc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;11-char bank branch code format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pincode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;6-digit PIN + postal zone lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mobile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10-digit Indian mobile + series check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;vehicle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;India vehicle registration format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;passport&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Indian passport number format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;upi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;UPI virtual payment address format&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Every validator returns the same clean object
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Human readable message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* optional extra info */&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;Consistent. Predictable. No surprises.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Aadhaar — Verhoeff checksum
&lt;/h3&gt;

&lt;p&gt;Most Aadhaar validators online just check if it's 12 digits. That's not enough.&lt;/p&gt;

&lt;p&gt;india-validators runs the actual Verhoeff algorithm — the same checksum UIDAI uses — to catch invalid numbers that pass the basic digit check.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aadhaar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;234567890123&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { valid: true, message: 'Valid Aadhaar format.' }&lt;/span&gt;

&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aadhaar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;123456789012&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { valid: false, message: 'Cannot start with 0 or 1.' }&lt;/span&gt;

&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aadhaar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;234567890124&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// valid digits, wrong checksum&lt;/span&gt;
&lt;span class="c1"&gt;// → { valid: false, message: 'Checksum failed — invalid Aadhaar.' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  PAN — entity type decoded
&lt;/h3&gt;

&lt;p&gt;PAN isn't just a format — the 4th character encodes the entity type. india-validators decodes it and returns it in &lt;code&gt;meta&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ABCPE1234F&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → {&lt;/span&gt;
&lt;span class="c1"&gt;//     valid: true,&lt;/span&gt;
&lt;span class="c1"&gt;//     message: 'Valid PAN format.',&lt;/span&gt;
&lt;span class="c1"&gt;//     meta: { entity: 'Individual', code: 'P' }&lt;/span&gt;
&lt;span class="c1"&gt;//   }&lt;/span&gt;

&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AAAPL1234C&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { meta: { entity: 'Company', code: 'C' } }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GSTIN — state + embedded PAN
&lt;/h3&gt;

&lt;p&gt;GSTIN contains the state code and the taxpayer's PAN. india-validators extracts both.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gstin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;27AAAPZ0327R1ZV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → {&lt;/span&gt;
&lt;span class="c1"&gt;//     valid: true,&lt;/span&gt;
&lt;span class="c1"&gt;//     message: 'Valid GSTIN.',&lt;/span&gt;
&lt;span class="c1"&gt;//     meta: {&lt;/span&gt;
&lt;span class="c1"&gt;//       state: 'Maharashtra',&lt;/span&gt;
&lt;span class="c1"&gt;//       stateCode: '27',&lt;/span&gt;
&lt;span class="c1"&gt;//       pan: 'AAAPZ0327R'&lt;/span&gt;
&lt;span class="c1"&gt;//     }&lt;/span&gt;
&lt;span class="c1"&gt;//   }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Mobile — strips country code automatically
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;+91 9876543210&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { valid: true, message: 'Valid Indian mobile number.' }&lt;/span&gt;

&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;09876543210&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { valid: true } // strips leading 0 automatically&lt;/span&gt;

&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5876543210&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → { valid: false, message: 'Must start with 6, 7, 8, or 9.' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UPI — known provider detection
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gaurav@okaxis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// → {&lt;/span&gt;
&lt;span class="c1"&gt;//     valid: true,&lt;/span&gt;
&lt;span class="c1"&gt;//     meta: { username: 'gaurav', handle: 'okaxis', knownProvider: true }&lt;/span&gt;
&lt;span class="c1"&gt;//   }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Batch validation — validate multiple fields at once
&lt;/h2&gt;

&lt;p&gt;The most useful feature for form validation:&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;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ABCPE1234F&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;mobile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;9876543210&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;gstin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;27AAAPZ0327R1ZV&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;pincode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;400001&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;// results.pan.valid     → true&lt;/span&gt;
&lt;span class="c1"&gt;// results.mobile.valid  → true&lt;/span&gt;
&lt;span class="c1"&gt;// results.gstin.meta.state → 'Maharashtra'&lt;/span&gt;
&lt;span class="c1"&gt;// results.pincode.meta.zone → 'Maharashtra, Goa, MP, Chhattisgarh'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One call. Clean results for every field.&lt;/p&gt;




&lt;h2&gt;
  
  
  Use in React
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;IndiaValidators&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;india-validators&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;KYCForm&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;pan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPan&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="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;IndiaValidators&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pan&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;div&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;input&lt;/span&gt;
                &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pan&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setPan&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="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter PAN"&lt;/span&gt;
            &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pan&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;span&lt;/span&gt; &lt;span class="na"&gt;style&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="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;valid&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&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;red&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;small&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Entity: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entity&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;small&lt;/span&gt;&lt;span class="p"&gt;&amp;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;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;h2&gt;
  
  
  Why checksums matter
&lt;/h2&gt;

&lt;p&gt;Most validators online use regex only. Regex catches format errors — wrong number of characters, wrong pattern. But it can't catch a number that looks right but isn't.&lt;/p&gt;

&lt;p&gt;Aadhaar uses the Verhoeff algorithm. GSTIN uses mod-36. india-validators implements both properly.&lt;/p&gt;

&lt;p&gt;This means fewer false positives in your forms — numbers that look valid but would be rejected by the actual government system get caught at the client side before they reach your backend.&lt;/p&gt;




&lt;h2&gt;
  
  
  Important disclaimer
&lt;/h2&gt;

&lt;p&gt;india-validators performs &lt;strong&gt;format and checksum validation only&lt;/strong&gt;. It does not connect to UIDAI, NSDL, GSTN, or any government API. It cannot verify identity. It cannot confirm a document is genuine.&lt;/p&gt;

&lt;p&gt;Always comply with applicable Indian laws when collecting and processing sensitive identifiers like Aadhaar and PAN.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;I'm a law student who also builds open source tools. I kept running into this problem — needing to validate Indian identifiers in projects and finding no clean library that handled it properly.&lt;/p&gt;

&lt;p&gt;india-validators is part of a growing set of open source tools I'm building for Indian developers under the gorupa namespace — alongside &lt;strong&gt;pulsekit.js&lt;/strong&gt; for PhonePe Pulse data visualisation and &lt;strong&gt;vaad.in&lt;/strong&gt; for court case tracking.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next — v0.2
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Voter ID format validation&lt;/li&gt;
&lt;li&gt;Driving licence (DL) format validation&lt;/li&gt;
&lt;li&gt;CIN — Company Identification Number&lt;/li&gt;
&lt;li&gt;TAN — Tax Deduction Account Number&lt;/li&gt;
&lt;li&gt;TypeScript definitions (.d.ts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PRs welcome. If you find a bug or a format that's wrong, open an issue.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://gorupa.github.io/india-validators/demo/" rel="noopener noreferrer"&gt;https://gorupa.github.io/india-validators/demo/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;npm:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/india-validators" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/india-validators&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Gorupa/india-validators" rel="noopener noreferrer"&gt;https://github.com/Gorupa/india-validators&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it saves you time — a star on GitHub means a lot.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built by &lt;a href="https://github.com/gorupa" rel="noopener noreferrer"&gt;@gorupa&lt;/a&gt; · MIT License · Zero dependencies&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built the first open source JS library for PhonePe Pulse data</title>
      <dc:creator>Gaurav Kalal</dc:creator>
      <pubDate>Sat, 14 Mar 2026 10:58:49 +0000</pubDate>
      <link>https://forem.com/gorupa/i-built-the-first-open-source-js-library-for-phonepe-pulse-datapublished-5306</link>
      <guid>https://forem.com/gorupa/i-built-the-first-open-source-js-library-for-phonepe-pulse-datapublished-5306</guid>
      <description>&lt;p&gt;PhonePe Pulse is one of the most interesting public datasets in India.&lt;/p&gt;

&lt;p&gt;It contains real UPI transaction data — broken down by state, district, category and quarter — going all the way back to 2018. It covers all 36 states. It updates every quarter. And it is completely free and open.&lt;/p&gt;

&lt;p&gt;The problem? It lives as raw JSON files in a GitHub repo. There is no SDK. No wrapper. No way to drop it into a project without writing a lot of fetch and parse logic yourself.&lt;/p&gt;

&lt;p&gt;So I built one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Introducing pulsekit.js
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;pulsekit.js&lt;/strong&gt; is a zero-dependency JavaScript library that wraps the PhonePe Pulse dataset and lets you render beautiful India payments charts with a single function call.&lt;/p&gt;

&lt;p&gt;No API key. No backend. No build step. Just one &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/gh/gorupa/pulsekit/src/pulsekit.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Three components out of the box
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📊 CategoryChart
&lt;/h3&gt;

&lt;p&gt;Shows transaction categories (P2P, P2M, Recharge, Financial Services, etc.) for any state and quarter as animated horizontal bars.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CategoryChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#chart&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;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;maharashtra&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;quarter&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;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// or 'amount'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you get — a clean card showing every transaction category for Maharashtra in Q1 2023, with animated bars and the actual transaction counts. All data fetched live from the PhonePe Pulse GitHub repo.&lt;/p&gt;




&lt;h3&gt;
  
  
  📈 GrowthChart
&lt;/h3&gt;

&lt;p&gt;A line chart showing UPI growth across every available quarter for a state — from 2018 all the way to 2023. Hover over any dot to see the exact value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;GrowthChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#chart&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;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;delhi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is my favourite. You can actually see India's UPI adoption curve in one chart. The growth from 2018 Q1 to 2023 Q4 is remarkable.&lt;/p&gt;




&lt;h3&gt;
  
  
  🏆 StateRanking
&lt;/h3&gt;

&lt;p&gt;Ranks all 36 Indian states by transaction volume or amount for a given period. You can control how many states to show.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StateRanking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#chart&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;year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;quarter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;count&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;top&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maharashtra, Karnataka and Delhi consistently dominate — but the growth in tier-2 states over recent years is the real story.&lt;/p&gt;




&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;pulsekit.js fetches data directly from &lt;code&gt;raw.githubusercontent.com/PhonePe/pulse&lt;/code&gt;. No proxy. No middleman. The data goes straight from PhonePe's public repo to your user's browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PhonePe Pulse GitHub repo
        ↓
raw.githubusercontent.com
        ↓
pulsekit.js fetch()
        ↓
Your chart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each component handles its own loading state, error state and animation. You just point it at a container and pass options.&lt;/p&gt;




&lt;h2&gt;
  
  
  Advanced usage
&lt;/h2&gt;

&lt;p&gt;For developers who want to go beyond the built-in components, all the data fetching utilities are exposed:&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;// Fetch one quarter for a state&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;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchStateQuarter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;karnataka&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2022&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="c1"&gt;// Fetch all quarters for a state&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;history&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;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchAllQuarters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rajasthan&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Fetch all states for a period — for custom ranking&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;states&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;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchAllStates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2023&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="c1"&gt;// Format helpers&lt;/span&gt;
&lt;span class="nx"&gt;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;formatCrore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;9870000000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// → "987.00 Cr"&lt;/span&gt;
&lt;span class="nx"&gt;PulseKit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDisplayName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tamil-nadu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// → "Tamil Nadu"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why I built this
&lt;/h2&gt;

&lt;p&gt;I'm a law student with a deep interest in India's digital infrastructure. I was building a small data dashboard and wanted to show UPI trends by state. The PhonePe Pulse data was exactly what I needed — but there was no clean way to use it.&lt;/p&gt;

&lt;p&gt;After writing the same fetch-and-render logic three times, I extracted it into a library. Then I thought — if I needed this, other developers do too.&lt;/p&gt;

&lt;p&gt;That's the whole story. A real problem, a clean solution, open sourced.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's next — v0.2
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;India choropleth map&lt;/strong&gt; — an SVG map of India where states are coloured by transaction intensity. This is the feature I'm most excited about.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NPCI data support&lt;/strong&gt; — monthly UPI stats from NPCI alongside PhonePe Pulse, making pulsekit.js the most complete India payments data library available.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React wrapper&lt;/strong&gt; — a proper &lt;code&gt;@gorupa/pulsekit-react&lt;/code&gt; package on npm.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://gorupa.github.io/pulsekit/demo/" rel="noopener noreferrer"&gt;https://gorupa.github.io/pulsekit/demo/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;⭐ &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Gorupa/pulsekit" rel="noopener noreferrer"&gt;https://github.com/Gorupa/pulsekit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;Data source:&lt;/strong&gt; &lt;a href="https://github.com/PhonePe/pulse" rel="noopener noreferrer"&gt;https://github.com/PhonePe/pulse&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find it useful — a star on GitHub goes a long way. And if you build something with it, I'd genuinely love to see it.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
