<?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: Naveen Hooda</title>
    <description>The latest articles on DEV Community by Naveen Hooda (@naveen_hooda_6953b0025c1f).</description>
    <link>https://dev.to/naveen_hooda_6953b0025c1f</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4036234%2F4b30fdf0-e27e-4b6d-b905-3819c5626ac0.png</url>
      <title>DEV Community: Naveen Hooda</title>
      <link>https://dev.to/naveen_hooda_6953b0025c1f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/naveen_hooda_6953b0025c1f"/>
    <language>en</language>
    <item>
      <title>Base64 is not encryption: what it is, when to use it, and the Unicode gotcha</title>
      <dc:creator>Naveen Hooda</dc:creator>
      <pubDate>Sat, 07 Nov 2026 06:23:22 +0000</pubDate>
      <link>https://dev.to/naveen_hooda_6953b0025c1f/base64-is-not-encryption-what-it-is-when-to-use-it-and-the-unicode-gotcha-42ho</link>
      <guid>https://dev.to/naveen_hooda_6953b0025c1f/base64-is-not-encryption-what-it-is-when-to-use-it-and-the-unicode-gotcha-42ho</guid>
      <description>&lt;p&gt;Every few months I see Base64 described as "encoding for security." It isn't. Here's what it actually does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Base64 is
&lt;/h2&gt;

&lt;p&gt;Base64 turns arbitrary bytes into text made only of safe characters (&lt;code&gt;A–Z&lt;/code&gt;, &lt;code&gt;a–z&lt;/code&gt;, &lt;code&gt;0–9&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;/&lt;/code&gt;, plus &lt;code&gt;=&lt;/code&gt; padding). That makes it possible to put binary data in places that only accept text: JSON, URLs, HTML, email.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Data URIs: &lt;code&gt;data:image/png;base64,...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;HTTP Basic auth headers&lt;/li&gt;
&lt;li&gt;Parts of JWTs&lt;/li&gt;
&lt;li&gt;Embedding small files in JSON APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it is not
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It's not encryption.&lt;/strong&gt; There's no key and no secret. Anyone can decode it instantly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;c2VjcmV0LXBhc3N3b3Jk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "secret-password"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see credentials "protected" with Base64, they're not protected.&lt;/p&gt;

&lt;h2&gt;
  
  
  It makes data bigger
&lt;/h2&gt;

&lt;p&gt;Every 3 bytes become 4 characters, so output is about &lt;strong&gt;33% larger&lt;/strong&gt;. That's fine for small icons and tokens, but a bad idea for large files.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Unicode gotcha
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;btoa&lt;/code&gt; only handles characters in the Latin-1 range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;héllo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// works&lt;/span&gt;
&lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;नमस्ते&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// InvalidCharacterError&lt;/span&gt;
&lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;😀&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// InvalidCharacterError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix is to convert text to UTF-8 bytes first:&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;toBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&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;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&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;binary&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="nx"&gt;bytes&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;b&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;binary&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromCharCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;btoa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fromBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b64&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;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b64&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;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;binary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;charCodeAt&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextDecoder&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;fromBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;toBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;नमस्ते 😀&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "नमस्ते 😀"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Base64URL: the URL-safe variant
&lt;/h2&gt;

&lt;p&gt;Standard Base64 uses &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;/&lt;/code&gt;, which have special meaning in URLs. Base64URL swaps them for &lt;code&gt;-&lt;/code&gt; and &lt;code&gt;_&lt;/code&gt; and usually drops the &lt;code&gt;=&lt;/code&gt; padding. JWTs use this variant, so decoding one with plain &lt;code&gt;atob&lt;/code&gt; can fail until you convert the characters back.&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;toStandard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/-/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/_/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick rules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use it to move binary data through text-only channels&lt;/li&gt;
&lt;li&gt;Don't use it to hide anything&lt;/li&gt;
&lt;li&gt;Avoid it for large files&lt;/li&gt;
&lt;li&gt;Always go through UTF-8 for non-English text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For quick checks while debugging, I use a &lt;a href="https://erapse.com/web-tools/base64-encoder-decoder.html" rel="noopener noreferrer"&gt;Base64 encoder/decoder&lt;/a&gt; from the free tools on Erapse, a site I run. For anything sensitive, decode locally instead.&lt;/p&gt;

&lt;p&gt;What's the strangest place you've found Base64 in the wild?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>security</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why 0.1 + 0.2 breaks your calculator (and how to handle money in JavaScript)</title>
      <dc:creator>Naveen Hooda</dc:creator>
      <pubDate>Sat, 07 Nov 2026 06:22:13 +0000</pubDate>
      <link>https://dev.to/naveen_hooda_6953b0025c1f/why-01-02-breaks-your-calculator-and-how-to-handle-money-in-javascript-5ch3</link>
      <guid>https://dev.to/naveen_hooda_6953b0025c1f/why-01-02-breaks-your-calculator-and-how-to-handle-money-in-javascript-5ch3</guid>
      <description>&lt;p&gt;Open your browser console and type:&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="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 0.30000000000000004&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's not a JavaScript bug. It's how binary floating point works, and it matters when you're building anything that handles money.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it happens
&lt;/h2&gt;

&lt;p&gt;JavaScript numbers are 64-bit binary floats. Just as 1/3 can't be written exactly in decimal, 0.1 can't be written exactly in binary. Tiny errors get stored, and they surface after arithmetic.&lt;/p&gt;

&lt;p&gt;Rounding is where it really bites:&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="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.005&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="c1"&gt;// "1.00"  (you probably expected "1.01")&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;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.005&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;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1     (same problem)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fix 1: Use integers for money
&lt;/h2&gt;

&lt;p&gt;Store amounts in the smallest unit, such as paise or cents, as whole numbers.&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;priceInPaise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;19999&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// ₹199.99&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;priceInPaise&lt;/span&gt; &lt;span class="o"&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;// 59997, exact&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Convert only when displaying. Integer arithmetic below 2^53 is exact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 2: Use a decimal library when you need decimals
&lt;/h2&gt;

&lt;p&gt;For things like tax or interest with many digits, libraries like &lt;code&gt;decimal.js&lt;/code&gt; or &lt;code&gt;big.js&lt;/code&gt; do arithmetic in base 10:&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="nx"&gt;Decimal&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;decimal.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;plus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "0.3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass numbers in as &lt;strong&gt;strings&lt;/strong&gt;, otherwise you've already introduced the error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix 3: Round once, at the end
&lt;/h2&gt;

&lt;p&gt;For estimates such as compound interest or SIP projections, floats are usually fine. The rule is: don't round intermediate steps, and round only when you show the result.&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;future&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt; &lt;span class="o"&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;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.12&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;future&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Format for humans, not by hand
&lt;/h2&gt;

&lt;p&gt;Don't write your own comma logic. &lt;code&gt;Intl.NumberFormat&lt;/code&gt; handles grouping and currency, including the Indian lakh style:&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;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-IN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1234567&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "12,34,567"&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en-IN&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;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1234567.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "₹12,34,567.50"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Never compare floats with &lt;code&gt;===&lt;/code&gt; after arithmetic&lt;/li&gt;
&lt;li&gt;Store money as integers or decimal strings&lt;/li&gt;
&lt;li&gt;Round only for display&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Intl.NumberFormat&lt;/code&gt; for formatting&lt;/li&gt;
&lt;li&gt;Test with awkward values like &lt;code&gt;1.005&lt;/code&gt;, &lt;code&gt;0.1 + 0.2&lt;/code&gt;, and very large amounts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want reference numbers to test against, calculators like the &lt;a href="https://erapse.com/compound-interest.html" rel="noopener noreferrer"&gt;compound interest&lt;/a&gt; and &lt;a href="https://erapse.com/sip.html" rel="noopener noreferrer"&gt;SIP&lt;/a&gt; tools on Erapse (my site) are useful for comparing results.&lt;/p&gt;

&lt;p&gt;Have you hit a floating-point bug in production? I'd like to hear about it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>How loan EMI is calculated: the formula, a JS implementation, and an amortization table</title>
      <dc:creator>Naveen Hooda</dc:creator>
      <pubDate>Sat, 07 Nov 2026 06:20:44 +0000</pubDate>
      <link>https://dev.to/naveen_hooda_6953b0025c1f/how-loan-emi-is-calculated-the-formula-a-js-implementation-and-an-amortization-table-2987</link>
      <guid>https://dev.to/naveen_hooda_6953b0025c1f/how-loan-emi-is-calculated-the-formula-a-js-implementation-and-an-amortization-table-2987</guid>
      <description>&lt;p&gt;Every loan app shows an EMI (equated monthly installment). The formula looks intimidating, but it's simple once you see where it comes from. Here's the math, an implementation, and a month-by-month breakdown.&lt;/p&gt;

&lt;h2&gt;
  
  
  The formula
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EMI = P × r × (1 + r)^n / ((1 + r)^n − 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;P&lt;/strong&gt; = principal (loan amount)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;r&lt;/strong&gt; = monthly interest rate (annual rate ÷ 12 ÷ 100)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n&lt;/strong&gt; = number of monthly payments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a fixed payment where the balance reaches exactly zero after &lt;code&gt;n&lt;/code&gt; payments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation
&lt;/h2&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;calculateEmi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;annualRatePercent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;years&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;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;12&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;annualRatePercent&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;12&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="c1"&gt;// Edge case: 0% interest would divide by zero in the formula&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;r&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;return&lt;/span&gt; &lt;span class="nx"&gt;principal&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;n&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;factor&lt;/span&gt; &lt;span class="o"&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;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&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;principal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;factor&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;factor&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="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculateEmi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&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="c1"&gt;// ≈ 8997.9 per month&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On ₹10,00,000 at 9% for 20 years, you pay about ₹21.6 lakh in total, so more than half of that is interest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the money actually goes: amortization
&lt;/h2&gt;

&lt;p&gt;Each month, interest is charged on the &lt;strong&gt;remaining balance&lt;/strong&gt;, and whatever is left of the EMI reduces the principal.&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;amortize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;annualRatePercent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;years&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;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;annualRatePercent&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;12&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;years&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;12&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;emi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculateEmi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;annualRatePercent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;years&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;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;principal&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;rows&lt;/span&gt; &lt;span class="o"&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;month&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;month&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;month&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;interest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;r&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;principalPaid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;emi&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;interest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;principalPaid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;rows&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;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;interest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;principalPaid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;balance&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;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&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="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;rows&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;In the first month of the example above, about ₹7,500 goes to interest and only about ₹1,500 reduces the loan. This is why early prepayments save so much: they cut the balance that interest is calculated on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge cases to handle
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero rate:&lt;/strong&gt; guard against division by zero, as above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Floating-point drift:&lt;/strong&gt; the final balance may be a tiny non-zero number. Clamp it, and round only for display.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invalid input:&lt;/strong&gt; negative or empty values should return an error, not &lt;code&gt;NaN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real lenders differ slightly:&lt;/strong&gt; rounding rules, processing fees, and daily vs. monthly compounding can change the figure by a few rupees.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it without writing code
&lt;/h2&gt;

&lt;p&gt;If you just want the numbers, there's a free &lt;a href="https://erapse.com/emi.html" rel="noopener noreferrer"&gt;EMI calculator&lt;/a&gt; and a &lt;a href="https://erapse.com/loan-comparison-calculator.html" rel="noopener noreferrer"&gt;loan comparison calculator&lt;/a&gt; on Erapse, a site I run. They're handy for sanity-checking your own implementation against.&lt;/p&gt;

&lt;p&gt;What would you add to a loan calculator? Prepayment simulation? Floating-rate changes?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>5 small debugging tasks I stopped doing by hand (JSON, JWT, Base64, timestamps, regex)</title>
      <dc:creator>Naveen Hooda</dc:creator>
      <pubDate>Sat, 07 Nov 2026 06:18:43 +0000</pubDate>
      <link>https://dev.to/naveen_hooda_6953b0025c1f/5-small-debugging-tasks-i-stopped-doing-by-hand-json-jwt-base64-timestamps-regex-509m</link>
      <guid>https://dev.to/naveen_hooda_6953b0025c1f/5-small-debugging-tasks-i-stopped-doing-by-hand-json-jwt-base64-timestamps-regex-509m</guid>
      <description>&lt;p&gt;Most of my debugging time isn't spent on hard problems. It's spent on small chores: reading a minified API response, checking what's inside a token, converting a timestamp. Here are five of them, what's actually going on in each, and the quickest way to handle them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Reading minified JSON
&lt;/h2&gt;

&lt;p&gt;An API returns one 4,000-character line and you need to find one field. Pretty-printing it makes the structure obvious, and validating it tells you where a malformed payload breaks.&lt;/p&gt;

&lt;p&gt;Common causes of "Unexpected token" errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A trailing comma after the last item&lt;/li&gt;
&lt;li&gt;Single quotes instead of double quotes&lt;/li&gt;
&lt;li&gt;Unquoted keys&lt;/li&gt;
&lt;li&gt;An HTML error page returned where you expected JSON (the error usually points at the first &lt;code&gt;&amp;lt;&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A formatter shows the exact line and character of the error. I use &lt;a href="https://erapse.com/web-tools/json-formatter.html" rel="noopener noreferrer"&gt;this JSON formatter and validator&lt;/a&gt; for quick checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. CSV to JSON (and back)
&lt;/h2&gt;

&lt;p&gt;You get a spreadsheet export and need JSON for a test fixture, or the reverse. The catch is quoting. A field like &lt;code&gt;"Smith, John"&lt;/code&gt; contains a comma, so a naive &lt;code&gt;split(",")&lt;/code&gt; breaks it.&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;// Fragile: breaks on quoted commas&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;csv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For one-off conversions, a converter saves the trouble. &lt;a href="https://erapse.com/web-tools/csv-to-json-converter.html" rel="noopener noreferrer"&gt;CSV to JSON&lt;/a&gt; and &lt;a href="https://erapse.com/web-tools/json-to-csv-converter.html" rel="noopener noreferrer"&gt;JSON to CSV&lt;/a&gt; cover both directions. For anything in production code, use a real parser such as Papa Parse.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Looking inside a JWT
&lt;/h2&gt;

&lt;p&gt;A JWT is three Base64URL-encoded parts separated by dots: &lt;code&gt;header.payload.signature&lt;/code&gt;. The header and payload are just JSON, so you can read them without any key:&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;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;atob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/-/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;+&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/_/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// { sub: "123", exp: 1767225600, ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Decoding is not verifying.&lt;/strong&gt; Anyone can read a JWT's contents. Only checking the signature with the right key tells you it's genuine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't paste live production tokens into random websites.&lt;/strong&gt; Use expired or test tokens, or decode locally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I just want to check &lt;code&gt;exp&lt;/code&gt; or &lt;code&gt;aud&lt;/code&gt; on a test token, a &lt;a href="https://erapse.com/web-tools/jwt-decoder.html" rel="noopener noreferrer"&gt;JWT decoder&lt;/a&gt; is faster than writing the snippet.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Unix timestamps
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;1767225600&lt;/code&gt; means nothing to a human. Two things trip people up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seconds vs. milliseconds.&lt;/strong&gt; Ten digits is seconds, thirteen digits is milliseconds. Passing seconds to JavaScript's &lt;code&gt;new Date()&lt;/code&gt; gives you a date in January 1970.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time zones.&lt;/strong&gt; Timestamps are UTC. The conversion to local time is where bugs appear.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1767225600&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A &lt;a href="https://erapse.com/web-tools/unix-timestamp-converter.html" rel="noopener noreferrer"&gt;timestamp converter&lt;/a&gt; is handy for checking logs.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Testing a regex before it ships
&lt;/h2&gt;

&lt;p&gt;Write the pattern against real sample input before putting it in code. Test the cases that usually break it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty strings&lt;/li&gt;
&lt;li&gt;Extra whitespace&lt;/li&gt;
&lt;li&gt;Multi-line input&lt;/li&gt;
&lt;li&gt;Unicode characters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watch for greedy matching (&lt;code&gt;.*&lt;/code&gt; grabs more than you expect) and for patterns with nested quantifiers like &lt;code&gt;(a+)+&lt;/code&gt;, which can cause catastrophic backtracking on bad input. A &lt;a href="https://erapse.com/web-tools/regex-tester.html" rel="noopener noreferrer"&gt;regex tester&lt;/a&gt; lets you iterate quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: other small tools worth bookmarking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://erapse.com/web-tools/base64-encoder-decoder.html" rel="noopener noreferrer"&gt;Base64 encoder/decoder&lt;/a&gt; for inspecting encoded payloads and data URIs&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://erapse.com/web-tools/text-diff-checker.html" rel="noopener noreferrer"&gt;Text diff checker&lt;/a&gt; for comparing two config files or API responses&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://erapse.com/web-tools/uuid-generator.html" rel="noopener noreferrer"&gt;UUID generator&lt;/a&gt; for test data&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;None of these tasks is hard. The time goes to context-switching and rewriting the same throwaway snippets. Bookmark a few tools, learn what each format is really doing, and save your focus for the real bugs.&lt;/p&gt;

&lt;p&gt;All the tools linked above are free and need no signup. They're part of &lt;a href="https://erapse.com/web-tools/index.html" rel="noopener noreferrer"&gt;Erapse&lt;/a&gt;, a site I run with free calculators and web tools. What small chores would you add to this list?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>How Online Calculators Actually Work: From Simple Math to Real-World Utility</title>
      <dc:creator>Naveen Hooda</dc:creator>
      <pubDate>Wed, 26 Aug 2026 05:26:26 +0000</pubDate>
      <link>https://dev.to/naveen_hooda_6953b0025c1f/how-online-calculators-actually-work-from-simple-math-to-real-world-utility-4c9k</link>
      <guid>https://dev.to/naveen_hooda_6953b0025c1f/how-online-calculators-actually-work-from-simple-math-to-real-world-utility-4c9k</guid>
      <description>&lt;p&gt;&lt;a href="https://erapse.com" rel="noopener noreferrer"&gt;Online calculators&lt;/a&gt; look simple from the outside: enter a few numbers, click a button, and get an answer.&lt;/p&gt;

&lt;p&gt;But building a useful calculator website involves much more than putting a mathematical formula into JavaScript.&lt;/p&gt;

&lt;p&gt;A good calculator needs accurate formulas, input validation, a clean user interface, mobile responsiveness, and explanations that help users understand the result.&lt;/p&gt;

&lt;p&gt;In this article, we'll look at how modern online calculators can be designed and what developers should consider when building them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start With the Formula
&lt;/h2&gt;

&lt;p&gt;Every calculator starts with a clearly defined mathematical formula.&lt;/p&gt;

&lt;p&gt;For example, a simple &lt;a href="https://www.erapse.com/percentage.html" rel="noopener noreferrer"&gt;percentage calculation&lt;/a&gt; can be represented as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Percentage = (Value / Total) × 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The formula itself is easy. The difficult part is handling real-world input.&lt;/p&gt;

&lt;p&gt;What happens if the user enters zero?&lt;/p&gt;

&lt;p&gt;What if they enter a negative number?&lt;/p&gt;

&lt;p&gt;What if the input is empty?&lt;/p&gt;

&lt;p&gt;A production-quality calculator should handle these cases gracefully instead of returning &lt;code&gt;NaN&lt;/code&gt; or an unexpected result.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Validate User Input
&lt;/h2&gt;

&lt;p&gt;Client-side validation is important for calculators.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculatePercentage&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="nx"&gt;total&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="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isFinite&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="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isFinite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;total&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="kc"&gt;null&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;total&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents invalid values from silently producing incorrect results.&lt;/p&gt;

&lt;p&gt;For more complex calculators, validation can include ranges, units, dates, decimal precision, and dependencies between inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Keep Calculation Logic Separate From the UI
&lt;/h2&gt;

&lt;p&gt;One useful development practice is separating the calculation function from the interface.&lt;/p&gt;

&lt;p&gt;Instead of putting all calculations inside a button click handler, create reusable functions:&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;calculateLoanPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;principal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;annualRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;months&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;monthlyRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;annualRate&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;12&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;monthlyRate&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;principal&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;months&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;principal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
        &lt;span class="nx"&gt;monthlyRate&lt;/span&gt; &lt;span class="o"&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;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;monthlyRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;months&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="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;monthlyRate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;months&lt;/span&gt;&lt;span class="p"&gt;)&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UI can then call this function and display the result.&lt;/p&gt;

&lt;p&gt;This makes the calculator easier to test and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Explain the Result
&lt;/h2&gt;

&lt;p&gt;A calculator should not only return a number.&lt;/p&gt;

&lt;p&gt;Users often want to know &lt;strong&gt;how the result was calculated&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, a loan calculator can show:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Principal amount&lt;/li&gt;
&lt;li&gt;Interest rate&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.erapse.com/loan-eligibility.html" rel="noopener noreferrer"&gt;Loan duration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Monthly payment&lt;/li&gt;
&lt;li&gt;Total interest&lt;/li&gt;
&lt;li&gt;Total amount payable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes the tool more transparent and useful.&lt;/p&gt;

&lt;p&gt;A good example is &lt;a href="https://www.erapse.com/" rel="noopener noreferrer"&gt;Erapse&lt;/a&gt;, which provides online calculators and utility tools designed around practical everyday calculations.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Make Calculators Mobile-Friendly
&lt;/h2&gt;

&lt;p&gt;A large percentage of users access online tools from smartphones.&lt;/p&gt;

&lt;p&gt;Therefore, calculator interfaces should work comfortably on small screens.&lt;/p&gt;

&lt;p&gt;Some basic considerations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use responsive layouts.&lt;/li&gt;
&lt;li&gt;Make input fields large enough to tap.&lt;/li&gt;
&lt;li&gt;Avoid unnecessarily wide tables.&lt;/li&gt;
&lt;li&gt;Keep important results visible.&lt;/li&gt;
&lt;li&gt;Use readable font sizes.&lt;/li&gt;
&lt;li&gt;Don't rely only on hover interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A calculator that works perfectly on desktop but is difficult to use on mobile will lose a significant portion of its potential audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Accuracy Matters More Than Design
&lt;/h2&gt;

&lt;p&gt;A calculator can have a beautiful interface, but if the calculation is wrong, users will stop trusting it.&lt;/p&gt;

&lt;p&gt;Developers should test calculators with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Normal values&lt;/li&gt;
&lt;li&gt;Zero values&lt;/li&gt;
&lt;li&gt;Very large values&lt;/li&gt;
&lt;li&gt;Decimal values&lt;/li&gt;
&lt;li&gt;Negative values where applicable&lt;/li&gt;
&lt;li&gt;Empty inputs&lt;/li&gt;
&lt;li&gt;Boundary values&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For &lt;a href="https://www.erapse.com/calculators/math-calculators/index.html" rel="noopener noreferrer"&gt;financial or scientific calculators&lt;/a&gt;, testing should also compare results against trusted formulas or reference calculations.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Don't Forget Units
&lt;/h2&gt;

&lt;p&gt;Unit conversion introduces another common source of errors.&lt;/p&gt;

&lt;p&gt;For example, converting kilometers to miles requires a defined conversion factor:&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;kilometersToMiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;km&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;km&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.621371&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 calculators involving multiple units, it is better to centralize conversion factors rather than duplicating them throughout the application.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. SEO for Calculator Websites
&lt;/h2&gt;

&lt;p&gt;Calculators can also be useful search-engine landing pages when they solve a specific problem.&lt;/p&gt;

&lt;p&gt;Instead of creating a page that only contains a calculator widget, developers can provide useful supporting information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the calculator does&lt;/li&gt;
&lt;li&gt;The formula used&lt;/li&gt;
&lt;li&gt;Step-by-step examples&lt;/li&gt;
&lt;li&gt;Common questions&lt;/li&gt;
&lt;li&gt;Explanation of inputs&lt;/li&gt;
&lt;li&gt;Limitations of the calculation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a better experience for both users and search engines.&lt;/p&gt;

&lt;p&gt;For example, instead of having only a "Percentage Calculator", a page could explain percentage increase, percentage decrease, the underlying formula, and several practical examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Build Small Tools That Solve Real Problems
&lt;/h2&gt;

&lt;p&gt;You don't always need a complicated application to create something useful.&lt;/p&gt;

&lt;p&gt;A simple calculator that solves a common problem can be more valuable than a large application that nobody needs.&lt;/p&gt;

&lt;p&gt;The best approach is usually:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identify a problem → define the formula → build a simple interface → validate inputs → explain the result → test extensively.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That process can turn a basic JavaScript function into a genuinely useful web tool.&lt;/p&gt;

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

&lt;p&gt;Online calculators are a good example of how relatively simple programming concepts can become useful products.&lt;/p&gt;

&lt;p&gt;The mathematics may sometimes be straightforward, but creating a reliable calculator requires attention to validation, usability, accuracy, accessibility, mobile design, and clear explanations.&lt;/p&gt;

&lt;p&gt;Whether you're building a calculator as a learning project or as part of a larger utility website, focus first on &lt;strong&gt;correctness and usefulness&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A calculator that solves one real problem accurately is often more valuable than a complicated tool that tries to do everything.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Built 250+ Free Online Calculators Using HTML, CSS, and JavaScript</title>
      <dc:creator>Naveen Hooda</dc:creator>
      <pubDate>Sun, 19 Jul 2026 07:58:00 +0000</pubDate>
      <link>https://dev.to/naveen_hooda_6953b0025c1f/how-i-built-250-free-online-calculators-using-html-css-and-javascript-5cl0</link>
      <guid>https://dev.to/naveen_hooda_6953b0025c1f/how-i-built-250-free-online-calculators-using-html-css-and-javascript-5cl0</guid>
      <description>&lt;p&gt;Building websites is easy.&lt;/p&gt;

&lt;p&gt;Building 250+ fast, SEO-friendly calculators that are easy to maintain is a completely different challenge.&lt;/p&gt;

&lt;p&gt;Over the past few months, I've been working on Erapse, a platform that provides free online calculators and utility tools. The goal is simple:&lt;/p&gt;

&lt;p&gt;Help people solve everyday problems quickly without requiring sign-ups, downloads, or unnecessary complexity.&lt;/p&gt;

&lt;p&gt;Why I Started This Project&lt;/p&gt;

&lt;p&gt;While searching online, I noticed that many calculators either:&lt;/p&gt;

&lt;p&gt;Are overloaded with advertisements&lt;br&gt;
Load slowly&lt;br&gt;
Provide very little explanation&lt;br&gt;
Aren't optimized for mobile devices&lt;br&gt;
Cover only a single category&lt;/p&gt;

&lt;p&gt;I wanted to build one platform where users could access calculators for different needs from one place.&lt;/p&gt;

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

&lt;p&gt;Finance&lt;br&gt;
Health&lt;br&gt;
Education&lt;br&gt;
Date &amp;amp; Time&lt;br&gt;
Unit Conversion&lt;br&gt;
Productivity&lt;br&gt;
Utility Tools&lt;br&gt;
Tech Stack&lt;/p&gt;

&lt;p&gt;I intentionally kept the stack simple.&lt;/p&gt;

&lt;p&gt;HTML5&lt;br&gt;
CSS3&lt;br&gt;
Bootstrap&lt;br&gt;
Vanilla JavaScript&lt;/p&gt;

&lt;p&gt;No heavy frontend framework.&lt;/p&gt;

&lt;p&gt;The main reason was performance and SEO.&lt;/p&gt;

&lt;p&gt;Each calculator loads almost instantly because there is very little JavaScript compared to a typical SPA.&lt;/p&gt;

&lt;p&gt;Reusable Architecture&lt;/p&gt;

&lt;p&gt;Instead of writing every calculator from scratch, I built reusable components.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Common input validation&lt;br&gt;
Shared UI components&lt;br&gt;
Error handling&lt;br&gt;
Copy/Reset functionality&lt;br&gt;
Responsive layout&lt;br&gt;
Shared styling&lt;/p&gt;

&lt;p&gt;That allows me to create new calculators much faster while keeping the user experience consistent.&lt;/p&gt;

&lt;p&gt;SEO Considerations&lt;/p&gt;

&lt;p&gt;Every calculator page includes:&lt;/p&gt;

&lt;p&gt;Unique title&lt;br&gt;
Meta description&lt;br&gt;
Structured headings&lt;br&gt;
Human-readable explanations&lt;br&gt;
Formula (when applicable)&lt;br&gt;
FAQs&lt;br&gt;
Related calculator links&lt;/p&gt;

&lt;p&gt;I also focused on:&lt;/p&gt;

&lt;p&gt;Fast page speed&lt;br&gt;
Mobile responsiveness&lt;br&gt;
Clean URLs&lt;br&gt;
Internal linking&lt;br&gt;
Challenges&lt;/p&gt;

&lt;p&gt;One thing I learned is that publishing hundreds of pages doesn't automatically generate traffic.&lt;/p&gt;

&lt;p&gt;The biggest challenges have been:&lt;/p&gt;

&lt;p&gt;Getting pages indexed&lt;br&gt;
Building topical authority&lt;br&gt;
Creating genuinely useful content&lt;br&gt;
Improving internal linking&lt;br&gt;
Earning trust from search engines&lt;/p&gt;

&lt;p&gt;SEO is definitely a long-term process.&lt;/p&gt;

&lt;p&gt;Lessons Learned&lt;/p&gt;

&lt;p&gt;Some things I'd recommend if you're building a similar project:&lt;/p&gt;

&lt;p&gt;✅ Keep your code reusable.&lt;/p&gt;

&lt;p&gt;✅ Focus on page speed.&lt;/p&gt;

&lt;p&gt;✅ Don't overcomplicate the frontend.&lt;/p&gt;

&lt;p&gt;✅ Write content that actually helps users.&lt;/p&gt;

&lt;p&gt;✅ Publish consistently.&lt;/p&gt;

&lt;p&gt;✅ Be patient with SEO.&lt;/p&gt;

&lt;p&gt;What's Next?&lt;/p&gt;

&lt;p&gt;I'm continuing to expand the platform with more calculators and utility tools.&lt;/p&gt;

&lt;p&gt;Some upcoming categories include:&lt;/p&gt;

&lt;p&gt;Government-related calculators&lt;br&gt;
Developer utilities&lt;br&gt;
PDF tools&lt;br&gt;
AI-powered utilities&lt;br&gt;
Productivity tools&lt;br&gt;
India-specific calculators&lt;/p&gt;

&lt;p&gt;The long-term goal is to build a comprehensive collection of useful online tools that anyone can access for free.&lt;/p&gt;

&lt;p&gt;I'd Love Your Feedback&lt;/p&gt;

&lt;p&gt;If you've built a large static website or a utility platform, I'd love to hear about your experience.&lt;/p&gt;

&lt;p&gt;How do you organize hundreds of pages?&lt;br&gt;
What SEO strategies have worked well for you?&lt;br&gt;
Any suggestions for improving scalability or maintainability?&lt;/p&gt;

&lt;p&gt;I'm always interested in learning from other developers.&lt;/p&gt;

&lt;p&gt;Project: &lt;a href="https://erapse.com" rel="noopener noreferrer"&gt;https://erapse.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have feedback or ideas for new calculators or utility tools, feel free to share them in the comments.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>javascript</category>
      <category>sideprojects</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
