<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Arpit Singhal</title>
    <description>The latest articles on Forem by Arpit Singhal (@arpit_singhal_2c86c804a6d).</description>
    <link>https://forem.com/arpit_singhal_2c86c804a6d</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%2F3675554%2Ff230cff3-f3ed-41e2-a60d-681fd67c1f10.png</url>
      <title>Forem: Arpit Singhal</title>
      <link>https://forem.com/arpit_singhal_2c86c804a6d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/arpit_singhal_2c86c804a6d"/>
    <language>en</language>
    <item>
      <title>I built a 'Forensic' Website Scanner using Next.js &amp; Cheerio (Open Source Logic)</title>
      <dc:creator>Arpit Singhal</dc:creator>
      <pubDate>Sat, 10 Jan 2026 14:26:40 +0000</pubDate>
      <link>https://forem.com/arpit_singhal_2c86c804a6d/i-built-a-forensic-website-scanner-using-nextjs-cheerio-open-source-logic-3nl1</link>
      <guid>https://forem.com/arpit_singhal_2c86c804a6d/i-built-a-forensic-website-scanner-using-nextjs-cheerio-open-source-logic-3nl1</guid>
      <description>&lt;p&gt;I got tired of inspecting elements manually, so I built an extension.&lt;/p&gt;

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

&lt;p&gt;It uses a custom scoring logic to detect 'Death Signals' like Parked Domains or 404s that standard tools miss.&lt;/p&gt;

&lt;p&gt;Link: Try it out here: &lt;a href="https://roastready.io" rel="noopener noreferrer"&gt;https://roastready.io&lt;/a&gt;&lt;br&gt;
Chrome Extension here:&lt;br&gt;
&lt;a href="https://chromewebstore.google.com/detail/ijgnchhhimmdcibhpanbgenhbhbfnaad?utm_source=item-share-cb" rel="noopener noreferrer"&gt;https://chromewebstore.google.com/detail/ijgnchhhimmdcibhpanbgenhbhbfnaad?utm_source=item-share-cb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Try it out (Break it!)
I’ve launched the MVP today. It’s free and doesn't require a login.
Live Tool: https://cleanmyprompt.io</title>
      <dc:creator>Arpit Singhal</dc:creator>
      <pubDate>Tue, 23 Dec 2025 17:39:23 +0000</pubDate>
      <link>https://forem.com/arpit_singhal_2c86c804a6d/try-it-out-break-it-ive-launched-the-mvp-today-its-free-and-doesnt-require-a-login-live-cm9</link>
      <guid>https://forem.com/arpit_singhal_2c86c804a6d/try-it-out-break-it-ive-launched-the-mvp-today-its-free-and-doesnt-require-a-login-live-cm9</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/arpit_singhal_2c86c804a6d" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3675554%2Ff230cff3-f3ed-41e2-a60d-681fd67c1f10.png" alt="arpit_singhal_2c86c804a6d"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/arpit_singhal_2c86c804a6d/i-built-a-privacy-firewall-for-chatgpt-using-nextjs-15-webassembly-100-offline-2820" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;I built a "Privacy Firewall" for ChatGPT using Next.js 15 &amp;amp; WebAssembly (100% Offline)&lt;/h2&gt;
      &lt;h3&gt;Arpit Singhal ・ Dec 23&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#nextjs&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#privacy&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://cleanmyprompt.io/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcleanmyprompt.io%2Fog-image.png" height="319" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://cleanmyprompt.io/" rel="noopener noreferrer" class="c-link"&gt;
            CleanMyPrompt | Free AI Token Optimizer &amp;amp; Privacy Tool
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Securely clean, compress, and anonymize text for ChatGPT. 100% offline processing.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcleanmyprompt.io%2Ficon.svg" width="180" height="180"&gt;
          cleanmyprompt.io
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>nextjs</category>
      <category>showdev</category>
      <category>privacy</category>
      <category>webdev</category>
    </item>
    <item>
      <title>I built a "Privacy Firewall" for ChatGPT using Next.js 15 &amp; WebAssembly (100% Offline)</title>
      <dc:creator>Arpit Singhal</dc:creator>
      <pubDate>Tue, 23 Dec 2025 17:14:32 +0000</pubDate>
      <link>https://forem.com/arpit_singhal_2c86c804a6d/i-built-a-privacy-firewall-for-chatgpt-using-nextjs-15-webassembly-100-offline-2820</link>
      <guid>https://forem.com/arpit_singhal_2c86c804a6d/i-built-a-privacy-firewall-for-chatgpt-using-nextjs-15-webassembly-100-offline-2820</guid>
      <description>&lt;p&gt;I use ChatGPT and Claude daily for coding. But last week, I had a mini heart attack.&lt;/p&gt;

&lt;p&gt;I was debugging a server log and pasted a huge block of text into the chat. Right before I hit "Enter," I realized the log contained a live &lt;strong&gt;Stripe Secret Key&lt;/strong&gt; and three customer email addresses.&lt;/p&gt;

&lt;p&gt;If I had sent that, it would have been in OpenAI's training logs forever.&lt;/p&gt;

&lt;p&gt;I looked for tools to "scrub" text, but they all required me to paste my data into &lt;em&gt;their&lt;/em&gt; website first. Sending my secrets to a random server to clean them defeated the whole purpose.&lt;/p&gt;

&lt;p&gt;So, I spent the weekend building my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Meet CleanMyPrompt
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://cleanmyprompt.io" rel="noopener noreferrer"&gt;CleanMyPrompt.io&lt;/a&gt;&lt;/strong&gt; is a browser-based utility that acts as a middleware between your clipboard and your AI.&lt;/p&gt;

&lt;p&gt;It runs entirely client-side. You can load the page, turn off your Wi-Fi, and it still works perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Accidental Leaks
&lt;/h2&gt;

&lt;p&gt;We get lazy. We &lt;code&gt;CMD+A&lt;/code&gt;, &lt;code&gt;CMD+C&lt;/code&gt;, &lt;code&gt;CMD+V&lt;/code&gt;.&lt;br&gt;
But LLMs ingest everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sk-live-...&lt;/code&gt; (API Keys)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user@company.com&lt;/code&gt; (PII)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;192.168.1.1&lt;/code&gt; (Internal IPs)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Solution: Client-Side Processing
&lt;/h2&gt;

&lt;p&gt;I built this using &lt;strong&gt;Next.js 15&lt;/strong&gt;. To ensure privacy, I made a strict architectural decision: &lt;strong&gt;No API Routes for text processing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything happens in the browser memory using JavaScript Regex and WebAssembly.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. The Redaction Logic (Regex)
&lt;/h3&gt;

&lt;p&gt;Here is a snippet of how the cleaner handles API keys locally. It looks for common patterns (like standard AWS or Stripe prefixes) and replaces them before the text creates a finalized string.&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;// Example: Detecting a Stripe Key pattern&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripeRegex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/sk_live_&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9a-zA-Z&lt;/span&gt;&lt;span class="se"&gt;]{24}&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;cleanText&lt;/span&gt; &lt;span class="o"&gt;=&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Simple chain to scrub sensitive data&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;input&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="nx"&gt;stripeRegex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[REDACTED_STRIPE_KEY]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;\b[\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;[\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;\.\w{2,4}\b&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;[EMAIL_REDACTED]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;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;0-9&lt;/span&gt;&lt;span class="se"&gt;]{1,3}\.){3}[&lt;/span&gt;&lt;span class="sr"&gt;0-9&lt;/span&gt;&lt;span class="se"&gt;]{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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[IP_ADDRESS]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Local OCR with WebAssembly
&lt;/h3&gt;

&lt;p&gt;I also wanted to grab text from screenshots (like error modals). Instead of using a cloud Vision API, I used &lt;strong&gt;Tesseract.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It loads the OCR engine as a WASM binary in a web worker. This means even image processing happens on your machine, not a cloud GPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Stack&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Framework&lt;/strong&gt;: Next.js 15 (App Router)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UI&lt;/strong&gt;: Tailwind CSS + Shadcn/UI&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Icons&lt;/strong&gt;: Lucide React&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OCR&lt;/strong&gt;: Tesseract.js (WASM)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deployment&lt;/strong&gt;: Vercel&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it out (Break it!)&lt;/strong&gt;&lt;br&gt;
I’ve launched the MVP today. It’s free and doesn't require a login.&lt;/p&gt;

&lt;p&gt;If you are paranoid about data privacy like me, give it a try next time you need to paste a log or code snippet into ChatGPT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live Tool&lt;/strong&gt;: &lt;a href="https://cleanmyprompt.io" rel="noopener noreferrer"&gt;https://cleanmyprompt.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me know if you find any edge cases where the regex fails!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>showdev</category>
      <category>privacy</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
