<?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: Ahnhyeongkyu</title>
    <description>The latest articles on DEV Community by Ahnhyeongkyu (@ahnhyeongkyu).</description>
    <link>https://dev.to/ahnhyeongkyu</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%2F3786389%2F1d8d4f5f-6fd9-4e83-bd3f-8d55903a2420.png</url>
      <title>DEV Community: Ahnhyeongkyu</title>
      <link>https://dev.to/ahnhyeongkyu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ahnhyeongkyu"/>
    <language>en</language>
    <item>
      <title>I Built a Testimonial.to Alternative — Here's What I Learned</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Mon, 13 Apr 2026 18:02:53 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/i-built-a-testimonialto-alternative-hwebdev-javascript-saas-buildinpubliceres-what-i-learned-2le3</link>
      <guid>https://dev.to/ahnhyeongkyu/i-built-a-testimonialto-alternative-hwebdev-javascript-saas-buildinpubliceres-what-i-learned-2le3</guid>
      <description>&lt;p&gt;I've been shipping products for a while now — StatMate, RoastSite, CodeNeat, RestInLight, and a few others. Every single one of them had the same problem: I'd get great feedback from users in DMs and emails, but none of it was visible on my landing pages.&lt;/p&gt;

&lt;p&gt;I looked at Testimonial.to. Great product, $2.4M ARR, clearly solving a real problem. But three things bugged me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The widget was heavy.&lt;/strong&gt; Loading a 50KB+ widget to show three quotes felt wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSS conflicts were constant.&lt;/strong&gt; Their widget styles would clash with my Tailwind setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No intelligence layer.&lt;/strong&gt; All testimonials were treated equally.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So I built &lt;a href="https://trustfolio.dev" rel="noopener noreferrer"&gt;Trustfolio&lt;/a&gt;. Here's the technical story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shadow DOM for Style Isolation
&lt;/h2&gt;

&lt;p&gt;If you've ever embedded a third-party widget on your site, you know the CSS collision nightmare. Shadow DOM solves this completely. The widget renders inside an encapsulated DOM tree with its own scoped styles. Zero leakage in either direction.&lt;/p&gt;

&lt;p&gt;The result: embed one line of code, and the widget looks exactly the same on every site, regardless of what CSS framework the host page uses.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sub-5KB Challenge
&lt;/h2&gt;

&lt;p&gt;Competitors ship 50-125KB widget bundles. Ours is under 5KB. How?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No framework runtime (vanilla JS, no React/Vue/Svelte)&lt;/li&gt;
&lt;li&gt;No CSS-in-JS library&lt;/li&gt;
&lt;li&gt;No external font loading&lt;/li&gt;
&lt;li&gt;Aggressive tree-shaking and minification&lt;/li&gt;
&lt;li&gt;Single IIFE bundle, zero external dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  AI Conversion Scoring
&lt;/h2&gt;

&lt;p&gt;This is the experimental part. Every testimonial gets analyzed on ingestion:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sentiment detection&lt;/strong&gt; — genuine enthusiasm vs. polite filler&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specificity scoring&lt;/strong&gt; — "saved 10 hours/week" scores higher than "great tool"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversion prediction&lt;/strong&gt; — 0-100 score based on specificity + emotion + outcome mentions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where I Am Now
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Product is live at &lt;a href="https://trustfolio.dev" rel="noopener noreferrer"&gt;trustfolio.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free tier: 15 testimonials, full AI features&lt;/li&gt;
&lt;li&gt;Pro: $29/mo, Business: $79/mo&lt;/li&gt;
&lt;li&gt;Using it on all my own products (dogfooding)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I'd love feedback on:&lt;/strong&gt; Is AI conversion scoring genuinely useful, or is it solving a problem that doesn't exist?&lt;/p&gt;

&lt;p&gt;Happy to answer any technical questions in the comments.&lt;/p&gt;

</description>
      <category>performance</category>
      <category>saas</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I Built 8 Developer Tools That Never See Your Code</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Sun, 12 Apr 2026 22:59:28 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/i-built-8-developer-tools-that-never-see-youwebdev-javascript-privacy-toolsr-code-4ma7</link>
      <guid>https://dev.to/ahnhyeongkyu/i-built-8-developer-tools-that-never-see-youwebdev-javascript-privacy-toolsr-code-4ma7</guid>
      <description>&lt;h2&gt;
  
  
  The Moment I Realized the Problem
&lt;/h2&gt;

&lt;p&gt;A few months ago, I was debugging a production issue at midnight. I had a large JSON config file that was not parsing correctly. I did what every developer does — I opened the first Google result for "json formatter online" and pasted my config.&lt;/p&gt;

&lt;p&gt;Then it hit me. That config contained database connection strings, API keys, and internal service URLs. I opened DevTools and checked the Network tab.&lt;/p&gt;

&lt;p&gt;Sure enough: a POST request carrying my entire input to the site's server. My production credentials had just traveled across the internet to a server I knew nothing about.&lt;/p&gt;

&lt;p&gt;I checked three more popular formatting sites. Same pattern. Every one of them sent the input to their backend for processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  This Is Not a Theoretical Risk
&lt;/h2&gt;

&lt;p&gt;Think about what developers paste into online tools on a daily basis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JSON files&lt;/strong&gt; containing API keys, database credentials, and service configurations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base64 strings&lt;/strong&gt; that encode authentication tokens and binary data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL queries&lt;/strong&gt; revealing table names, column structures, and business logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWTs&lt;/strong&gt; containing user identities, roles, and session data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regex patterns&lt;/strong&gt; tested against real production data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code diffs&lt;/strong&gt; showing proprietary source code changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The leading online developer tool sites handle tens of millions of visits per month. That is an enormous volume of sensitive developer data flowing through third-party servers every day.&lt;/p&gt;

&lt;p&gt;And here is the thing: &lt;strong&gt;none of these operations require a server.&lt;/strong&gt; JSON formatting, Base64 encoding, URL encoding, regex matching, text diffing, JWT decoding, SQL formatting, hash generation — all of these can be done entirely in the browser with JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  So I Built CodeNeat
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://codeneat.dev" rel="noopener noreferrer"&gt;CodeNeat&lt;/a&gt; is a set of 8 developer tools where every operation runs 100% in your browser. No data is ever sent to any server for processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 8 Tools
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;a href="https://codeneat.dev/json-formatter" rel="noopener noreferrer"&gt;JSON Formatter &amp;amp; Viewer&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Format, validate, minify, and explore JSON with syntax highlighting and interactive tree view.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. &lt;a href="https://codeneat.dev/base64-encode-decode" rel="noopener noreferrer"&gt;Base64 Encode/Decode&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Encode and decode Base64 strings. Instant results with zero server round-trip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. &lt;a href="https://codeneat.dev/url-encode-decode" rel="noopener noreferrer"&gt;URL Encode/Decode&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Full Unicode support for URL encoding and decoding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. &lt;a href="https://codeneat.dev/regex-tester" rel="noopener noreferrer"&gt;Regex Tester&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Real-time matching with capture groups and flag controls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. &lt;a href="https://codeneat.dev/diff-checker" rel="noopener noreferrer"&gt;Diff Checker&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Side-by-side text comparison with line-level highlighting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. &lt;a href="https://codeneat.dev/jwt-decoder" rel="noopener noreferrer"&gt;JWT Decoder&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Decode and inspect JWTs — header, payload, signature, expiration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. &lt;a href="https://codeneat.dev/sql-formatter" rel="noopener noreferrer"&gt;SQL Formatter&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Multi-dialect SQL formatting. Your queries never leave the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. &lt;a href="https://codeneat.dev/hash-generator" rel="noopener noreferrer"&gt;Hash Generator&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
MD5, SHA-1, SHA-256, SHA-512. All computation via Web Crypto API.&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Each tool is a pure TypeScript function in &lt;code&gt;lib/tools/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/tools/json.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;indent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&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;parsed&lt;/span&gt; &lt;span class="o"&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="nx"&gt;input&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;indent&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;These functions are imported directly into React client components. No &lt;code&gt;fetch()&lt;/code&gt;. No &lt;code&gt;XMLHttpRequest&lt;/code&gt;. No server endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Verify
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Method 1: DevTools
&lt;/h3&gt;

&lt;p&gt;Open any tool on &lt;a href="https://codeneat.dev" rel="noopener noreferrer"&gt;codeneat.dev&lt;/a&gt;, open DevTools Network tab, filter by Fetch/XHR, use the tool. Zero processing requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 2: Offline
&lt;/h3&gt;

&lt;p&gt;Load any tool, disconnect from the internet, use the tool. It works because the processing never needed a server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Method 3: Source Code
&lt;/h3&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/Ahnhyeongkyu/codeneat" rel="noopener noreferrer"&gt;github.com/Ahnhyeongkyu/codeneat&lt;/a&gt;. Search for &lt;code&gt;fetch(&lt;/code&gt; in &lt;code&gt;lib/tools/&lt;/code&gt;. Zero results.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Framework:&lt;/strong&gt; Next.js 16 with App Router&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS v4 + shadcn/ui&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment:&lt;/strong&gt; Vercel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Is Next
&lt;/h2&gt;

&lt;p&gt;A Chrome extension that brings these tools into the browser toolbar. The core logic ports directly since it is pure functions.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://codeneat.dev" rel="noopener noreferrer"&gt;codeneat.dev&lt;/a&gt; — free, no account required.&lt;/p&gt;

&lt;p&gt;If useful: &lt;a href="https://github.com/Ahnhyeongkyu/codeneat" rel="noopener noreferrer"&gt;Star on GitHub&lt;/a&gt; to help others discover it.&lt;/p&gt;

&lt;p&gt;Your code should stay yours. That is not a feature — it should be the default.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>security</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Stop Shipping 300KB Testimonial Widgets — There's a Better Way</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Sat, 28 Mar 2026 04:29:09 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/stop-shipping-300kb-testimonial-wiwebdev-saas-javascript-testimonialsdgets-theres-a-better-way-3039</link>
      <guid>https://dev.to/ahnhyeongkyu/stop-shipping-300kb-testimonial-wiwebdev-saas-javascript-testimonialsdgets-theres-a-better-way-3039</guid>
      <description>&lt;p&gt;If you've ever added a testimonial widget to your site, you probably noticed the performance hit. Most popular solutions load 200-300KB of JavaScript, inject iframes, and tank your Core Web Vitals.&lt;/p&gt;

&lt;p&gt;I run five different web products. Every one of them needed social proof. And every testimonial tool I tried made the same trade-off: nice-looking widgets that quietly destroyed page speed.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://trustfolio.dev" rel="noopener noreferrer"&gt;Trustfolio&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Here's what a typical testimonial widget does to your site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;200-300KB&lt;/strong&gt; of JavaScript loaded on every page&lt;/li&gt;
&lt;li&gt;Layout shift from async-loaded content&lt;/li&gt;
&lt;li&gt;Extra DNS lookups and third-party connections&lt;/li&gt;
&lt;li&gt;No way to know which testimonials actually drive conversions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Trustfolio Is Different
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Under 5KB Widget
&lt;/h3&gt;

&lt;p&gt;The entire embed script is under 5KB gzipped. It uses Shadow DOM for style isolation, loads async, and renders in under 100ms. Zero layout shift.&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;div&lt;/span&gt; &lt;span class="na"&gt;data-trustfolio=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_WIDGET_ID"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&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://trustfolio.dev/embed.js"&lt;/span&gt; &lt;span class="na"&gt;async&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;That's it. Two lines. No iframes, no external CSS, no layout shift.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. AI That Knows What Converts
&lt;/h3&gt;

&lt;p&gt;Instead of manually picking which testimonials to show, Trustfolio's AI analyzes every submission:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sentiment Analysis&lt;/strong&gt; — scores emotional tone from 0 to 1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Highlights&lt;/strong&gt; — finds the most persuasive phrases automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversion Score&lt;/strong&gt; — rates each testimonial 0-100 based on how likely it is to drive action&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Tagging&lt;/strong&gt; — categorizes by topic (support, pricing, features, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Six Widget Layouts
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layout&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wall of Love&lt;/td&gt;
&lt;td&gt;Landing pages, dedicated testimonial sections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carousel&lt;/td&gt;
&lt;td&gt;Limited space, above the fold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Badge&lt;/td&gt;
&lt;td&gt;Compact trust signals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single Card&lt;/td&gt;
&lt;td&gt;Hero sections, sidebars&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Popup&lt;/td&gt;
&lt;td&gt;Exit intent, time-delayed social proof&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Marquee&lt;/td&gt;
&lt;td&gt;Continuous scrolling banners&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Multiple Collection Methods
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom collection pages&lt;/strong&gt; — branded forms with your questions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import from CSV&lt;/strong&gt; — migrate from other tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google/G2 imports&lt;/strong&gt; — pull existing reviews (more sources coming)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Architecture
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16&lt;/strong&gt; with Edge Runtime for the OG image API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Neon (serverless Postgres)&lt;/strong&gt; via Drizzle ORM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shadow DOM&lt;/strong&gt; (closed mode) for widget style isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;sendBeacon&lt;/strong&gt; for analytics tracking without blocking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI analysis&lt;/strong&gt; powered by Claude API&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt;: 10 testimonials, 1 widget, wall layout&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro&lt;/strong&gt; ($29/mo): Unlimited testimonials, all layouts, AI analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Business&lt;/strong&gt; ($79/mo): Everything + API access, white label, A/B testing&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;If you're running a SaaS, portfolio, or any site that shows customer feedback, give it a shot: &lt;a href="https://trustfolio.dev" rel="noopener noreferrer"&gt;trustfolio.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Free tier is genuinely usable — no credit card, no trial expiration. I'd appreciate any feedback from the dev community.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>I Built a Sub-5KB Testimonial Widget Because Every Alternative Tanked My Lighthouse Score</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Fri, 27 Mar 2026 11:51:25 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/i-built-a-sub-5kb-testimonial-widget-becauswebdev-javascript-saas-aie-every-alternative-tanked-55l4</link>
      <guid>https://dev.to/ahnhyeongkyu/i-built-a-sub-5kb-testimonial-widget-becauswebdev-javascript-saas-aie-every-alternative-tanked-55l4</guid>
      <description>&lt;p&gt;Every testimonial widget I tried added 200-500KB to my pages. My Lighthouse scores dropped. My ads got more expensive because pages loaded slower.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://trustfolio.dev" rel="noopener noreferrer"&gt;Trustfolio&lt;/a&gt; — a testimonial platform where the entire embed widget is under 5KB gzipped.&lt;/p&gt;

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

&lt;p&gt;Most testimonial tools treat performance as an afterthought. They load heavy JavaScript bundles, inject their own CSS that conflicts with yours, and add hundreds of milliseconds to your page load.&lt;/p&gt;

&lt;p&gt;Research shows each second of delay reduces conversions by 4.42%. If you're running paid ads, slow pages = wasted ad spend.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Trustfolio&lt;/strong&gt; is a full testimonial management platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Collect&lt;/strong&gt;: Shareable collection pages (text + video, no sign-up needed for customers)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analyze&lt;/strong&gt;: AI-powered sentiment analysis, theme detection, and highlight suggestions using Claude Haiku&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display&lt;/strong&gt;: 5 widget layouts — Wall, Carousel, Badge, Popup, Marquee&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track&lt;/strong&gt;: Conversion tracking to see which testimonials actually drive sign-ups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The embed widget uses Shadow DOM for zero CSS conflicts and loads in under 10ms from CDN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Next.js + React&lt;/li&gt;
&lt;li&gt;Drizzle ORM + Neon PostgreSQL (serverless)&lt;/li&gt;
&lt;li&gt;Clerk Auth (GitHub + Google + Email)&lt;/li&gt;
&lt;li&gt;Claude Haiku API for AI analysis&lt;/li&gt;
&lt;li&gt;Shadow DOM embed widget (3.1KB gzipped)&lt;/li&gt;
&lt;li&gt;Vercel deployment&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Trustfolio is live with a generous free tier — 15 testimonials, 1 widget, full AI analysis. No credit card required.&lt;/p&gt;

&lt;p&gt;Check it out: &lt;a href="https://trustfolio.dev" rel="noopener noreferrer"&gt;trustfolio.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear your feedback!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Regex Lookahead and Lookbehind: Patterns Every Developer Should Know</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Wed, 04 Mar 2026 02:40:11 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/regex-lookahead-and-lookbehind-patterns-every-developer-should-know-2lb</link>
      <guid>https://dev.to/ahnhyeongkyu/regex-lookahead-and-lookbehind-patterns-every-developer-should-know-2lb</guid>
      <description>&lt;p&gt;Lookaheads and lookbehinds are the regex features that separate "I know regex" from "I &lt;em&gt;know&lt;/em&gt; regex." They let you match patterns based on what comes before or after — without including that context in the match itself.&lt;/p&gt;

&lt;p&gt;Once you understand them, problems that seemed impossible with basic regex become straightforward. Let's break them down.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Lookaheads and Lookbehinds?
&lt;/h2&gt;

&lt;p&gt;Think of regular expressions as a cursor moving through text. Normally, every part of your pattern consumes characters — the cursor advances as it matches. Lookaheads and lookbehinds are different: they &lt;strong&gt;peek&lt;/strong&gt; at surrounding text without consuming it. The cursor looks, but doesn't move.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An analogy:&lt;/strong&gt; Imagine you're searching a bookshelf for books with red covers. A normal regex is like pulling each book off the shelf to check it. A lookahead is like glancing at the next book without pulling it out. A lookbehind is like glancing at the previous book. You're gathering information, but you're not removing anything from the shelf.&lt;/p&gt;

&lt;p&gt;This "zero-width" property is what makes them powerful. You can assert that certain text exists nearby without including it in your match result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Four Types: A Syntax Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Syntax&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Positive Lookahead&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(?=...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What follows &lt;strong&gt;must&lt;/strong&gt; match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative Lookahead&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(?!...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What follows &lt;strong&gt;must not&lt;/strong&gt; match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Positive Lookbehind&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(?&amp;lt;=...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What precedes &lt;strong&gt;must&lt;/strong&gt; match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative Lookbehind&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(?&amp;lt;!...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;What precedes &lt;strong&gt;must not&lt;/strong&gt; match&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The key to remembering the syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;=&lt;/code&gt; means positive (it &lt;strong&gt;does&lt;/strong&gt; match)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;!&lt;/code&gt; means negative (it &lt;strong&gt;doesn't&lt;/strong&gt; match)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;&lt;/code&gt; means look &lt;strong&gt;behind&lt;/strong&gt; (to the left)&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;&amp;lt;&lt;/code&gt; means look &lt;strong&gt;ahead&lt;/strong&gt; (to the right)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's put them to work with five real-world examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 1: Password Validation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Validate that a password contains at least one uppercase letter, one lowercase letter, one digit, and is at least 8 characters long.&lt;/p&gt;

&lt;p&gt;Without lookaheads, you'd need to check each condition separately or write an absurdly complex alternation. With lookaheads, you can stack multiple conditions at the same position:&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;passwordRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\d)&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;{8,}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Test cases&lt;/span&gt;
&lt;span class="nx"&gt;passwordRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyPass1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// true — has upper, lower, digit, 8+ chars&lt;/span&gt;
&lt;span class="nx"&gt;passwordRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mypass1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// false — no uppercase&lt;/span&gt;
&lt;span class="nx"&gt;passwordRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MYPASS1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// false — no lowercase&lt;/span&gt;
&lt;span class="nx"&gt;passwordRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyPassword&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// false — no digit&lt;/span&gt;
&lt;span class="nx"&gt;passwordRegex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Mp1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// false — too short&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works, step by step:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;^&lt;/code&gt; — Start of string&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?=.*[A-Z])&lt;/code&gt; — Lookahead: somewhere ahead there's an uppercase letter. The cursor doesn't move.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?=.*[a-z])&lt;/code&gt; — Lookahead: somewhere ahead there's a lowercase letter. Still at position 0.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?=.*\d)&lt;/code&gt; — Lookahead: somewhere ahead there's a digit. Still at position 0.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.{8,}$&lt;/code&gt; — Now actually consume: match 8 or more of any character to the end.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All three lookaheads fire from the same starting position. They each independently scan the entire string for their condition. Only when all three succeed does the engine proceed to the actual match.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding more rules&lt;/strong&gt; is trivial. Need a special character too?&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;strongPassword&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;A-Z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-z&lt;/span&gt;&lt;span class="se"&gt;])(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;\d)(?=&lt;/span&gt;&lt;span class="sr"&gt;.*&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;!@#$%^&amp;amp;*&lt;/span&gt;&lt;span class="se"&gt;])&lt;/span&gt;&lt;span class="sr"&gt;.&lt;/span&gt;&lt;span class="se"&gt;{10,}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example 2: Extract Prices Without Currency Symbols
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; You have text containing prices in various formats and you want to extract just the numeric values, without the currency symbol.&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Products: $49.99, €120.00, £75.50, $1,299.00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Positive lookbehind: match numbers preceded by a currency symbol&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;priceRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;=&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;$€£&lt;/span&gt;&lt;span class="se"&gt;])\d[\d&lt;/span&gt;&lt;span class="sr"&gt;,.&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;/g&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;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;priceRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; ['49.99', '120.00', '75.50', '1,299.00']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;(?&amp;lt;=[$€£])&lt;/code&gt; — Lookbehind: the position must be preceded by &lt;code&gt;$&lt;/code&gt;, &lt;code&gt;€&lt;/code&gt;, or &lt;code&gt;£&lt;/code&gt;. This symbol is NOT included in the match.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\d[\d,.]*\d&lt;/code&gt; — Match digits, possibly with commas and decimal points in between.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The beauty here is that the currency symbols are used to locate the right numbers but aren't captured. Without a lookbehind, you'd need a capture group and an extra extraction step:&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;// Without lookbehind (less clean)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;$€£&lt;/span&gt;&lt;span class="se"&gt;](\d[\d&lt;/span&gt;&lt;span class="sr"&gt;,.&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\d)&lt;/span&gt;&lt;span class="sr"&gt;/g&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fallback&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;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lookbehind version is more direct and readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 3: Match Words NOT Followed by Specific Text
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; In a codebase, find all uses of &lt;code&gt;import&lt;/code&gt; that are NOT followed by &lt;code&gt;type&lt;/code&gt; (you want value imports, not TypeScript type imports).&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;`
import React from 'react';
import type { FC } from 'react';
import { useState } from 'react';
import type { Props } from './types';
import axios from 'axios';
&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;;

const valueImports = /import(?!\s+type)\s+.+/g;
const matches = code.match(valueImports);
// =&amp;gt; [
//   "import React from 'react';",
//   "import { useState } from 'react';",
//   "import axios from 'axios';"
// ]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;import&lt;/code&gt; — Match the literal text "import"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?!\s+type)&lt;/code&gt; — Negative lookahead: what follows must NOT be whitespace + "type"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;\s+.+&lt;/code&gt; — Then consume the rest of the import statement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The negative lookahead acts as a filter. It says "yes, I found &lt;code&gt;import&lt;/code&gt;, but only keep it if &lt;code&gt;type&lt;/code&gt; doesn't come next."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another practical use — excluding test files:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Match .js files that are NOT test files&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;(?!\.&lt;/span&gt;&lt;span class="sr"&gt;test&lt;/span&gt;&lt;span class="se"&gt;)\.&lt;/span&gt;&lt;span class="sr"&gt;js/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app.js utils.test.js config.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; ['app.js', 'config.js']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example 4: Parse Structured Log Files
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; You're parsing log entries and need to extract the log level, but only from lines that contain an IP address (indicating network-related events).&lt;/p&gt;

&lt;p&gt;Sample log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2026-03-01 10:15:32 [ERROR] Connection timeout from 192.168.1.100
2026-03-01 10:15:33 [INFO] Cache cleared successfully
2026-03-01 10:15:34 [WARN] Rate limit approaching for 10.0.0.55
2026-03-01 10:15:35 [DEBUG] Query executed in 42ms
2026-03-01 10:15:36 [ERROR] SSL handshake failed from 172.16.0.200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;`2026-03-01 10:15:32 [ERROR] Connection timeout from 192.168.1.100
2026-03-01 10:15:33 [INFO] Cache cleared successfully
2026-03-01 10:15:34 [WARN] Rate limit approaching for 10.0.0.55
2026-03-01 10:15:35 [DEBUG] Query executed in 42ms
2026-03-01 10:15:36 [ERROR] SSL handshake failed from 172.16.0.200&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;;

// Positive lookahead: match log level only if an IP address appears later in the line
const networkLogs = /\[(ERROR|WARN|INFO|DEBUG)\](?=.*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/gm;

const matches = [...logs.matchAll(networkLogs)].map(m =&amp;gt; m[1]);
// =&amp;gt; ['ERROR', 'WARN', 'ERROR']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;\[(ERROR|WARN|INFO|DEBUG)\]&lt;/code&gt; — Match the log level in brackets, capturing the level name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?=.*\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})&lt;/code&gt; — Lookahead: somewhere on this line, there's an IP address pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lines without IP addresses (the INFO cache line and the DEBUG query line) are excluded. The lookahead lets you filter on content that appears much later in the line without having to match everything in between.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Combining with lookbehind to extract the IP itself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Extract IPs that appear after the word "from"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fromIPs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;=from&lt;/span&gt;&lt;span class="se"&gt;\s)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fromIPs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; ['192.168.1.100', '172.16.0.200']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example 5: Email Username Extraction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Extract the username portion of email addresses (everything before the &lt;code&gt;@&lt;/code&gt;) from a block of text.&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;`
Contact us:
  - Support: support@codeneat.dev
  - Sales: sales.team@codeneat.dev
  - Bug reports: bugs+tracker@codeneat.dev
&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;;

// Positive lookahead: match word characters (plus dots, hyphens, and +)
// that are followed by @
const usernameRegex = /[\w.+-]+(?=@)/g;

const usernames = text.match(usernameRegex);
// =&amp;gt; ['support', 'sales.team', 'bugs+tracker']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[\w.+-]+&lt;/code&gt; — Match one or more word characters, dots, plus signs, or hyphens&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;(?=@)&lt;/code&gt; — Lookahead: this match must be followed by &lt;code&gt;@&lt;/code&gt;, but don't include &lt;code&gt;@&lt;/code&gt; in the result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without the lookahead, you'd match the &lt;code&gt;@&lt;/code&gt; and then have to strip 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;// Without lookahead&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;([\w&lt;/span&gt;&lt;span class="sr"&gt;.+-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;@/g&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;matches&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fallback&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;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;m&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lookahead version is cleaner because the match itself is exactly what you want.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extracting the domain instead (using lookbehind):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;domainRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;=@&lt;/span&gt;&lt;span class="se"&gt;)[\w&lt;/span&gt;&lt;span class="sr"&gt;.-&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domainRegex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; ['codeneat.dev', 'codeneat.dev', 'codeneat.dev']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Browser and Engine Support
&lt;/h2&gt;

&lt;p&gt;Lookaheads have been supported everywhere for decades. Lookbehinds are newer — here's the current status:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Chrome&lt;/th&gt;
&lt;th&gt;Firefox&lt;/th&gt;
&lt;th&gt;Safari&lt;/th&gt;
&lt;th&gt;Node.js&lt;/th&gt;
&lt;th&gt;Edge&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Positive Lookahead &lt;code&gt;(?=...)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative Lookahead &lt;code&gt;(?!...)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;td&gt;All versions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Positive Lookbehind &lt;code&gt;(?&amp;lt;=...)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;62+&lt;/td&gt;
&lt;td&gt;78+&lt;/td&gt;
&lt;td&gt;16.4+&lt;/td&gt;
&lt;td&gt;8.10+&lt;/td&gt;
&lt;td&gt;79+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative Lookbehind &lt;code&gt;(?&amp;lt;!...)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;62+&lt;/td&gt;
&lt;td&gt;78+&lt;/td&gt;
&lt;td&gt;16.4+&lt;/td&gt;
&lt;td&gt;8.10+&lt;/td&gt;
&lt;td&gt;79+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Key takeaway:&lt;/strong&gt; As of 2026, lookbehinds are safe to use in all modern browsers. The only concern is if you need to support Safari 16.3 or older (released early 2023). For server-side JavaScript (Node.js), lookbehinds have been available since Node 8.&lt;/p&gt;

&lt;p&gt;If you need to support older environments, you can always rewrite lookbehinds using capture groups:&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;// Lookbehind version (modern)&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;(?&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;g
&lt;/span&gt;
&lt;span class="c1"&gt;// Capture group equivalent (universal)&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;  &lt;span class="c1"&gt;// then use match[1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Variable-length lookbehinds:&lt;/strong&gt; JavaScript supports variable-length lookbehinds, but some regex engines (notably older Python &lt;code&gt;re&lt;/code&gt; module) don't. If your pattern works in JS but fails elsewhere, this might be why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Performance with &lt;code&gt;.*&lt;/code&gt; in lookaheads:&lt;/strong&gt; Patterns like &lt;code&gt;(?=.*something)&lt;/code&gt; cause the engine to scan the entire remaining string. In tight loops or very long strings, stack multiple specific lookaheads rather than using greedy quantifiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Forgetting that lookarounds are zero-width:&lt;/strong&gt; A common mistake is expecting &lt;code&gt;(?=foo)bar&lt;/code&gt; to match "foobar". It won't — after the lookahead asserts "foo" is ahead, the cursor is still at the same position, and it tries to match "bar" starting where "foo" starts. You'd want &lt;code&gt;(?=foo)foobar&lt;/code&gt; or just &lt;code&gt;foobar&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Your Patterns Live
&lt;/h2&gt;

&lt;p&gt;Regex is a skill you build by doing. Reading about lookaheads is useful; writing and testing them is where the understanding clicks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test these patterns live at &lt;a href="https://codeneat.dev/regex-tester" rel="noopener noreferrer"&gt;codeneat.dev/regex-tester&lt;/a&gt;&lt;/strong&gt; — it provides real-time match highlighting, capture group visualization, and runs entirely in your browser so your test data stays private.&lt;/p&gt;

&lt;p&gt;Paste any of the examples from this article and experiment. Change the patterns, try different inputs, and build intuition for how lookaheads and lookbehinds actually work.&lt;/p&gt;

</description>
      <category>regex</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Complete Guide to JSON Syntax Errors (With Examples and Fixes)</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Wed, 04 Mar 2026 02:35:24 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/the-complete-guide-to-json-syntax-errors-with-examples-and-fixes-36kl</link>
      <guid>https://dev.to/ahnhyeongkyu/the-complete-guide-to-json-syntax-errors-with-examples-and-fixes-36kl</guid>
      <description>&lt;p&gt;If you've ever stared at &lt;code&gt;Unexpected token ... in JSON at position ...&lt;/code&gt; and had no idea what went wrong, this guide is for you.&lt;/p&gt;

&lt;p&gt;JSON looks simple — and it is. But its strictness catches developers off guard constantly. Unlike JavaScript objects, JSON has zero tolerance for syntax shortcuts. One wrong character and the entire document fails to parse.&lt;/p&gt;

&lt;p&gt;Here are the 7 most common JSON syntax errors, why they happen, and how to fix each one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error 1: Trailing Commas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The single most common JSON error.&lt;/strong&gt; You'll hit this one more than all others combined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broken:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"developer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token } in JSON at position 56
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; JavaScript objects and arrays happily accept trailing commas. JSON does not. When you copy an object literal from your code into a &lt;code&gt;.json&lt;/code&gt; file or an API request body, that trailing comma comes along for the ride.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"developer"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript detection and fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Quick fix: strip trailing commas before parsing&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;removeTrailingCommas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonString&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;jsonString&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;/,&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;([\]&lt;/span&gt;&lt;span class="sr"&gt;}&lt;/span&gt;&lt;span class="se"&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="s1"&gt;$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleaned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;removeTrailingCommas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"a": 1, "b": 2,}&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;parsed&lt;/span&gt; &lt;span class="o"&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="nx"&gt;cleaned&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Arrays have the same issue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;BROKEN&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blue"&lt;/span&gt;&lt;span class="p"&gt;,]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;FIXED&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blue"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error 2: Single Quotes Instead of Double Quotes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Broken:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;'name':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;'active':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token ' in JSON at position 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; JavaScript allows single quotes, backticks, and double quotes for strings. JSON only allows double quotes. Period. This is defined in &lt;a href="https://tools.ietf.org/html/rfc8259" rel="noopener noreferrer"&gt;RFC 8259&lt;/a&gt; and there are no exceptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"active"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript detection and fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Replace single-quoted keys and values with double quotes&lt;/span&gt;
&lt;span class="c1"&gt;// WARNING: This is a naive approach — use a proper parser for production&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;singleToDoubleQuotes&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&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="s1"&gt;"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Better approach: use JSON5 for lenient parsing&lt;/span&gt;
&lt;span class="c1"&gt;// npm install json5&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;JSON5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json5&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;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON5&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{'name': 'Alice'}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; { name: "Alice" }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error 3: Unquoted Keys
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Broken:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;age:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token n in JSON at position 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; JavaScript object literals allow unquoted keys when the key is a valid identifier. JSON requires every key to be a double-quoted string — no exceptions, even for simple alphanumeric keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript tip:&lt;/strong&gt; If you're generating JSON from code, always use &lt;code&gt;JSON.stringify()&lt;/code&gt; rather than constructing strings manually. It handles quoting automatically:&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;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&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;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&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;// Produces valid JSON with double-quoted keys every time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error 4: Comments in JSON
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Broken:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Database&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;settings&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;default&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;PostgreSQL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;*/&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token / in JSON at position 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Standard JSON (RFC 8259) has no comment syntax at all. No &lt;code&gt;//&lt;/code&gt;, no &lt;code&gt;/* */&lt;/code&gt;, no &lt;code&gt;#&lt;/code&gt;. This is an intentional design choice by Douglas Crockford — JSON is a data format, not a configuration language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed (option A — remove comments):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5432&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"database"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fixed (option B — use a format that supports comments):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you genuinely need comments in your config files, consider these alternatives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JSONC&lt;/strong&gt; (JSON with Comments) — used by VS Code's &lt;code&gt;settings.json&lt;/code&gt;, TypeScript's &lt;code&gt;tsconfig.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON5&lt;/strong&gt; — superset of JSON that supports comments, trailing commas, and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;YAML&lt;/strong&gt; — full comment support with &lt;code&gt;#&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;JavaScript strip-and-parse:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Strip single-line and multi-line comments from a JSON string&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stripJsonComments&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&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;/&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="sr"&gt;.*$/gm&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="c1"&gt;// Remove // comments&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;/&lt;/span&gt;&lt;span class="se"&gt;\/\*[\s\S]&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&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="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Remove /* */ comments&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;/,&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;([\]&lt;/span&gt;&lt;span class="sr"&gt;}&lt;/span&gt;&lt;span class="se"&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="s1"&gt;$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// Clean up any resulting trailing commas&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;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;`{
  // server config
  "host": "localhost",
  "port": 5432
}&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;;

const parsed = JSON.parse(stripJsonComments(raw));
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Error 5: undefined, NaN, and Infinity
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Broken:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"middleName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Infinity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token u in JSON at position 32
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt;, and &lt;code&gt;-Infinity&lt;/code&gt; are JavaScript-specific values. They have no representation in JSON. The only valid JSON values are: strings, numbers (finite), booleans (&lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt;), &lt;code&gt;null&lt;/code&gt;, objects, and arrays.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"middleName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript handling with &lt;code&gt;JSON.stringify&lt;/code&gt; replacer:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;middleName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;Infinity&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Default behavior: undefined properties are SILENTLY DROPPED&lt;/span&gt;
&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// =&amp;gt; '{"name":"Alice","score":null,"limit":null}'&lt;/span&gt;
&lt;span class="c1"&gt;// Note: middleName is gone entirely, NaN and Infinity become null&lt;/span&gt;

&lt;span class="c1"&gt;// Custom replacer for explicit control:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&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="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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&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;p&gt;Watch out: &lt;code&gt;JSON.stringify()&lt;/code&gt; silently drops &lt;code&gt;undefined&lt;/code&gt; properties rather than converting them to &lt;code&gt;null&lt;/code&gt;. This catches people off guard when they expect round-trip consistency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error 6: BOM (Byte Order Mark) Characters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Broken (invisible!):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The JSON looks perfectly valid in your editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But parsing fails with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token ﻿ in JSON at position 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; Some text editors (notably older versions of Notepad on Windows, and some Excel CSV exports) prepend an invisible UTF-8 BOM character (&lt;code&gt;\uFEFF&lt;/code&gt;) to files. It's invisible in most editors but causes &lt;code&gt;JSON.parse()&lt;/code&gt; to choke because the first character isn't &lt;code&gt;{&lt;/code&gt; or &lt;code&gt;[&lt;/code&gt; — it's a zero-width no-break space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to detect it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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="nx"&gt;raw&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="c1"&gt;// 65279 = BOM is present&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;raw&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="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s1"&gt;uFEFF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;JavaScript fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;stripBOM&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;str&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="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xFEFF&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="nf"&gt;slice&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="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;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&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;parsed&lt;/span&gt; &lt;span class="o"&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;stripBOM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prevention:&lt;/strong&gt; Configure your editor to save files without BOM. In VS Code, check the encoding indicator in the bottom status bar — it should say "UTF-8", not "UTF-8 with BOM".&lt;/p&gt;

&lt;h2&gt;
  
  
  Error 7: Missing or Mismatched Brackets
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Broken:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The error:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected token } in JSON at position 79
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it happens:&lt;/strong&gt; The &lt;code&gt;users&lt;/code&gt; array was opened with &lt;code&gt;[&lt;/code&gt; but never closed with &lt;code&gt;]&lt;/code&gt;. In deeply nested JSON documents — especially those with hundreds of lines — it's easy to lose track of bracket pairs. A single missing bracket or brace invalidates the entire document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to find the problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The error position (&lt;code&gt;at position 79&lt;/code&gt;) tells you where the parser gave up, but the actual mistake is usually earlier in the document. Here's a systematic approach:&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;findBracketMismatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonString&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;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pairs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{&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;}&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;[&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;]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;jsonString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonString&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stack&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;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;char&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;last&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="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;`Extra closing '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' at position &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;);
        return;
      }
      if (pairs[last.char] !== char) {
        console.log(&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;Mismatch: '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;last&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; closed by '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' at &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;);
        return;
      }
    }
  }

  if (stack.length &amp;gt; 0) {
    const unclosed = stack.pop();
    console.log(&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;Unclosed '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;unclosed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;char&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;' at position &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;unclosed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;);
  }
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A Defensive Parsing Pattern
&lt;/h2&gt;

&lt;p&gt;In production code, you should never call &lt;code&gt;JSON.parse()&lt;/code&gt; without error handling. Here's a robust pattern:&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;safeJsonParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Step 1: Strip BOM if present&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleaned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;raw&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="o"&gt;===&lt;/span&gt; &lt;span class="mh"&gt;0xFEFF&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&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="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Step 2: Attempt parse&lt;/span&gt;
  &lt;span class="k"&gt;try&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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cleaned&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="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;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;err&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="c1"&gt;// Extract position from error message&lt;/span&gt;
        &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/position &lt;/span&gt;&lt;span class="se"&gt;(\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/&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="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;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="c1"&gt;// Usage&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="nf"&gt;safeJsonParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;`Parse error at position &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;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;);
} else {
  console.log(result.data);
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quick Reference: JSON vs JavaScript Objects
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;JavaScript Object&lt;/th&gt;
&lt;th&gt;JSON&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Trailing commas&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Single quotes&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unquoted keys&lt;/td&gt;
&lt;td&gt;Allowed (identifiers)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comments&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;NaN&lt;/code&gt; / &lt;code&gt;Infinity&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Functions as values&lt;/td&gt;
&lt;td&gt;Allowed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Not allowed&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key order&lt;/td&gt;
&lt;td&gt;Preserved (mostly)&lt;/td&gt;
&lt;td&gt;Preserved (mostly)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Stop Guessing, Start Validating
&lt;/h2&gt;

&lt;p&gt;The fastest way to debug JSON issues is to use a proper validator that pinpoints the exact error location and suggests fixes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validate your JSON instantly at &lt;a href="https://codeneat.dev/json-formatter" rel="noopener noreferrer"&gt;codeneat.dev/json-formatter&lt;/a&gt;&lt;/strong&gt; — it highlights syntax errors inline, shows the exact position of the problem, and runs entirely in your browser so your data stays private.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Your Online Dev Tools Might Be Leaking Your Code (And What to Do About It)</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Wed, 04 Mar 2026 02:27:41 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/why-your-online-dev-tools-might-be-leaking-your-code-and-what-to-do-about-it-23e5</link>
      <guid>https://dev.to/ahnhyeongkyu/why-your-online-dev-tools-might-be-leaking-your-code-and-what-to-do-about-it-23e5</guid>
      <description>&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Picture this: you're debugging an API response at 11 PM. The JSON blob is a mess — deeply nested, minified, impossible to read. You do what every developer does: copy, open your favorite online formatter, paste, done.&lt;/p&gt;

&lt;p&gt;But here's the thing. That JSON blob contained an API key. A user's email address. Maybe a session token. And the tool you just pasted it into? It sent every byte to a remote server.&lt;/p&gt;

&lt;p&gt;This isn't a hypothetical scenario. It happens millions of times a day across the developer community. We've trained ourselves to be paranoid about hardcoding secrets, we rotate keys religiously, we use environment variables — and then we paste production data into a random website's text area without blinking.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Bad Is It, Really?
&lt;/h2&gt;

&lt;p&gt;Let's run a simple experiment. Open any popular online JSON formatter. Now open your browser's DevTools, switch to the &lt;strong&gt;Network&lt;/strong&gt; tab, and paste some JSON.&lt;/p&gt;

&lt;p&gt;Watch what happens.&lt;/p&gt;

&lt;p&gt;On many tools, you'll see an outbound POST request the moment you click "Format." Your data just traveled to someone else's server. Depending on the tool's privacy practices, that data might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Logged&lt;/strong&gt; for debugging or analytics purposes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cached&lt;/strong&gt; on their CDN or application server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Processed&lt;/strong&gt; server-side with no guaranteed deletion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stored&lt;/strong&gt; in backups that persist for months&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now multiply this across every tool in your workflow. JWT decoders, Base64 converters, regex testers, SQL formatters. Every paste is a potential data leak.&lt;/p&gt;

&lt;h3&gt;
  
  
  What's Actually at Risk?
&lt;/h3&gt;

&lt;p&gt;Think about what developers routinely paste into online tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JWT tokens&lt;/strong&gt; — contain user IDs, roles, permissions, email addresses, and expiration data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API responses&lt;/strong&gt; — often include PII (names, emails, phone numbers), internal IDs, and business logic details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configuration files&lt;/strong&gt; — database connection strings, API keys, service credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQL queries&lt;/strong&gt; — table names, column structures, business logic encoded in WHERE clauses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hash inputs&lt;/strong&gt; — passwords being tested, secret keys being verified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A single paste can expose more about your infrastructure than a careless README ever could.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fix: Client-Side-Only Processing
&lt;/h2&gt;

&lt;p&gt;The solution is straightforward: use tools that never send your data anywhere. &lt;strong&gt;Client-side-only&lt;/strong&gt; tools run all processing logic in your browser using JavaScript. The data you paste stays in your browser tab and is never transmitted over the network.&lt;/p&gt;

&lt;p&gt;This isn't a marketing claim you have to take on faith — it's something you can verify yourself in 10 seconds with your browser's Network tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codeneat.dev" rel="noopener noreferrer"&gt;CodeNeat&lt;/a&gt; is a collection of developer tools built on exactly this principle. Every tool runs 100% in the browser. No server calls, no analytics on your input data, no exceptions.&lt;/p&gt;

&lt;p&gt;Let me walk you through three tools and show you what privacy-first development tooling looks like in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool 1: JSON Formatter — The One You Use Most
&lt;/h2&gt;

&lt;p&gt;JSON formatting is probably the most common task in any developer's day. CodeNeat's &lt;a href="https://codeneat.dev/json-formatter" rel="noopener noreferrer"&gt;JSON Formatter&lt;/a&gt; handles it entirely in the browser.&lt;/p&gt;

&lt;p&gt;It instantly formats with proper indentation, syntax highlighting, and a collapsible tree view. You can switch between 2-space and 4-space indentation, minify it back, or explore nested structures using the tree viewer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The privacy angle:&lt;/strong&gt; Open the Network tab — you'll see zero outbound requests related to your data.&lt;/p&gt;

&lt;p&gt;The tool also supports JSON Path queries, so you can extract specific data without ever sending the full document anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool 2: JWT Decoder — Where Privacy Matters Most
&lt;/h2&gt;

&lt;p&gt;JWTs are arguably the most sensitive data developers routinely paste into online tools. A typical JWT payload contains user IDs, permission models, organizational structure — all encoded in a token.&lt;/p&gt;

&lt;p&gt;CodeNeat's &lt;a href="https://codeneat.dev/jwt-decoder" rel="noopener noreferrer"&gt;JWT Decoder&lt;/a&gt; splits the token into its three parts (header, payload, signature), decodes each one, and displays the result with syntax highlighting. It flags expired tokens and shows human-readable timestamps.&lt;/p&gt;

&lt;p&gt;Everything happens in your browser. The JWT never leaves your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tool 3: Hash Generator — Verify Without Exposing
&lt;/h2&gt;

&lt;p&gt;CodeNeat's &lt;a href="https://codeneat.dev/hash-generator" rel="noopener noreferrer"&gt;Hash Generator&lt;/a&gt; supports MD5, SHA-1, SHA-256, and SHA-512. Type or paste your input, and the hashes are computed instantly in the browser using the Web Crypto API.&lt;/p&gt;

&lt;p&gt;No server ever sees your input. The hash computation runs in a Web Worker to keep the UI responsive, even for large inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Verify Any Tool's Privacy Claims
&lt;/h2&gt;

&lt;p&gt;Don't take anyone's word for it — including mine. Here's a 30-second verification process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open DevTools&lt;/strong&gt; (F12 or Cmd+Option+I)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Go to the Network tab&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check "Preserve log"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paste your data&lt;/strong&gt; into the tool and trigger processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect every request&lt;/strong&gt; — check the Payload/Request Body tab&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you see your input data in an outbound request, that tool is server-side. If the only requests are for static assets, the tool is genuinely client-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Individual Tools: Building Privacy Into Your Workflow
&lt;/h2&gt;

&lt;p&gt;Privacy-first tooling isn't just about individual tools. It's a mindset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audit your bookmarks.&lt;/strong&gt; How many of your saved dev tools are server-side?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check before you paste.&lt;/strong&gt; If the data contains anything sensitive, verify the tool's processing model first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Educate your team.&lt;/strong&gt; Share this Network-tab verification technique in your next team standup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider compliance.&lt;/strong&gt; If you handle GDPR-covered data or HIPAA records, pasting it into server-side tools may be a compliance violation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;We lock down our repos, rotate our keys, encrypt our databases, and audit our dependencies. But we paste sensitive data into random websites every single day.&lt;/p&gt;

&lt;p&gt;It's time to close that gap. Client-side tools aren't a compromise — they're faster (no network round-trip), work offline, and provably protect your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it yourself at &lt;a href="https://codeneat.dev" rel="noopener noreferrer"&gt;codeneat.dev&lt;/a&gt; — and open your Network tab to verify.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built a Free Statistics Calculator with Next.js — Here's What I Learned</title>
      <dc:creator>Ahnhyeongkyu</dc:creator>
      <pubDate>Mon, 23 Feb 2026 10:24:56 +0000</pubDate>
      <link>https://dev.to/ahnhyeongkyu/i-built-a-free-statistics-calculator-with-nextjs-heres-what-i-learned-4ic6</link>
      <guid>https://dev.to/ahnhyeongkyu/i-built-a-free-statistics-calculator-with-nextjs-heres-what-i-learned-4ic6</guid>
      <description>&lt;p&gt;As a developer who also does research, I got tired of switching between SPSS, R, and Excel just to run basic statistical tests. So I built &lt;strong&gt;StatMate&lt;/strong&gt; — a free, browser-based statistics calculator that handles 20 different tests and outputs APA-formatted results.&lt;/p&gt;

&lt;p&gt;Here's the story of how I built it and what I learned along the way.&lt;/p&gt;

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

&lt;p&gt;Every semester, thousands of students and researchers face the same struggle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SPSS costs $100+/month&lt;/li&gt;
&lt;li&gt;R has a steep learning curve&lt;/li&gt;
&lt;li&gt;Excel can't format APA tables automatically&lt;/li&gt;
&lt;li&gt;Online calculators only handle one test at a time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to build something that just &lt;em&gt;works&lt;/em&gt; — paste your data, pick a test, get properly formatted results.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js 16&lt;/strong&gt; with Turbopack for fast builds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TypeScript&lt;/strong&gt; for type-safe statistics calculations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind CSS v4&lt;/strong&gt; for styling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;next-intl&lt;/strong&gt; for trilingual support (English, Korean, Japanese)&lt;/li&gt;
&lt;li&gt;All statistics computed &lt;strong&gt;client-side&lt;/strong&gt; in the browser — no data leaves your machine&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;StatMate currently supports &lt;strong&gt;20 statistical tests&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parametric: t-tests (independent, paired, one-sample), ANOVA (one-way, two-way, repeated measures), simple &amp;amp; multiple regression, logistic regression&lt;/li&gt;
&lt;li&gt;Non-parametric: Mann-Whitney U, Wilcoxon, Kruskal-Wallis, Friedman&lt;/li&gt;
&lt;li&gt;Other: Chi-square, Fisher's exact, McNemar, correlation, descriptive stats, sample size/power, Cronbach's alpha, factor analysis (EFA)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every test includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;APA 7th edition formatted results&lt;/strong&gt; — copy-paste ready&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assumption checks&lt;/strong&gt; (normality, homogeneity of variance)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive charts&lt;/strong&gt; (box plots, scatter plots, residual plots)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDF export&lt;/strong&gt; (free) and Word/DOCX export (Pro)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example data&lt;/strong&gt; so users can try before entering their own&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Implementing Statistics from Scratch
&lt;/h3&gt;

&lt;p&gt;No external stats library — I wrote all 20 statistical modules in TypeScript. The trickiest parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Matrix operations&lt;/strong&gt; for factor analysis (eigenvalue decomposition, varimax rotation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probability distributions&lt;/strong&gt; (t, F, chi-square) using series approximations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post-hoc tests&lt;/strong&gt; (Bonferroni, Tukey HSD, Dunn's test)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I validated every calculator against R 4.3 to ensure accuracy.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. APA Formatting
&lt;/h3&gt;

&lt;p&gt;APA 7th edition has very specific formatting rules. Each test has its own reporting format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;t(58) = 2.45, p = .017, d = 0.63
F(2, 87) = 4.12, p = .019, partial eta-squared = .086
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Building a system that automatically generates these strings with correct rounding, italics handling, and effect size interpretation was more work than expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. i18n for Statistics
&lt;/h3&gt;

&lt;p&gt;Translating a statistics app into 3 languages isn't just about UI text. Statistical terminology, APA conventions, and number formatting all vary by locale. &lt;code&gt;next-intl&lt;/code&gt; handled most of it, but edge cases required custom logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Client-side computation is underrated.&lt;/strong&gt; Users trust a tool more when their data never leaves the browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APA formatting is a product feature&lt;/strong&gt;, not a nice-to-have. It's the #1 thing users mention.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trilingual from day one&lt;/strong&gt; opened up markets I wouldn't have reached otherwise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free tools need a Pro tier&lt;/strong&gt; to be sustainable. Ours includes AI-powered result interpretation and DOCX export.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;StatMate is live at &lt;a href="https://statmate.org" rel="noopener noreferrer"&gt;statmate.org&lt;/a&gt;. Everything is free — 20 calculators, PDF export, assumption checks, and charts.&lt;/p&gt;

&lt;p&gt;If you're building tools for researchers or students, I'd love to hear about your experience. Drop a comment or check out the project!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions about implementing statistics in JavaScript, APA formatting, or building multilingual Next.js apps? Happy to discuss in the comments.&lt;/em&gt;&lt;/p&gt;

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