<?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: Pranav</title>
    <description>The latest articles on DEV Community by Pranav (@pranav_503667748505fccf1b).</description>
    <link>https://dev.to/pranav_503667748505fccf1b</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4081954%2Fcd685f60-c21b-4cdf-91e7-adeaee74ebb5.png</url>
      <title>DEV Community: Pranav</title>
      <link>https://dev.to/pranav_503667748505fccf1b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pranav_503667748505fccf1b"/>
    <language>en</language>
    <item>
      <title>Every "Free" PDF Editor Wants Your Resume First. I Got Tired of Uploading It.</title>
      <dc:creator>Pranav</dc:creator>
      <pubDate>Mon, 17 Aug 2026 17:03:02 +0000</pubDate>
      <link>https://dev.to/pranav_503667748505fccf1b/every-free-pdf-editor-wants-your-resume-first-i-got-tired-of-uploading-it-340p</link>
      <guid>https://dev.to/pranav_503667748505fccf1b/every-free-pdf-editor-wants-your-resume-first-i-got-tired-of-uploading-it-340p</guid>
      <description>&lt;p&gt;I needed to fix a typo on my resume last year — one line, wrong phone number — and it took longer than it should have because I refused to do the obvious thing: type "free pdf editor" into Google and use the first result.&lt;/p&gt;

&lt;p&gt;Here's why. Every one of those tools works the same way. You drag your PDF into the browser, it gets &lt;strong&gt;uploaded to a server&lt;/strong&gt;, something processes it, and a few seconds later you download the result. That's the entire model. And the file that just made that round trip was my resume — home address, phone number, employment history, sometimes references — sitting on a server operated by a company whose terms of service I definitely didn't read.&lt;/p&gt;

&lt;p&gt;Most people don't think about this, because "upload" has become such an invisible verb online that it barely registers as a decision anymore. But it is one. And for a PDF specifically, it's a decision you're often making with your most sensitive documents: signed contracts, tax forms, medical records, your CV.&lt;/p&gt;

&lt;h2&gt;
  
  
  The watermark problem is the same problem in disguise
&lt;/h2&gt;

&lt;p&gt;The other thing you'll notice, if you've used any of the big free PDF sites, is the watermark. Merge two files for free and you get a diagonal logo stamped across your output — or a hard cap of three files, or a "sign up to continue" wall after your second edit. iLovePDF, Smallpdf, Adobe's free tier — they all do some version of this, and it's not really a technical limitation. It's a business model: give away just enough to get you hooked, then monetize the friction.&lt;/p&gt;

&lt;p&gt;The watermark and the upload are connected, even though they don't look related. Both come from the same underlying architecture: your file goes to a server, the server does the work, and now the server-owner controls the terms of getting your file back — watermark included, subscription optional. If the processing never leaves your device in the first place, there's no server-side gatekeeper to add a watermark or throttle you at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I switched to
&lt;/h2&gt;

&lt;p&gt;I ended up on &lt;a href="https://www.ihatepdf.cv" rel="noopener noreferrer"&gt;ihatepdf.cv&lt;/a&gt;, which does the PDF editing directly in the browser using WebAssembly — meaning the "upload" step just doesn't exist. There's nowhere for the file to go, because nothing is sent anywhere. You open the &lt;a href="https://www.ihatepdf.cv/edit-pdf-text" rel="noopener noreferrer"&gt;PDF editor&lt;/a&gt;, click the typo, fix it, and download — and the whole thing happens on your own machine.&lt;/p&gt;

&lt;p&gt;A few things stood out using it for actual tasks, not just the privacy pitch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No watermark, ever&lt;/strong&gt; — not a "pay to remove" watermark, just none, on any of the 46 tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It works with no internet after the first load&lt;/strong&gt; — I've since used it on a flight to &lt;a href="https://www.ihatepdf.cv/merge-pdf" rel="noopener noreferrer"&gt;merge&lt;/a&gt; some contracts, which isn't something you can do with an upload-based tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No account, no email, no "sign up to download."&lt;/strong&gt; You use the tool and you're done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.ihatepdf.cv/redact-pdf" rel="noopener noreferrer"&gt;Redaction&lt;/a&gt; and a privacy scanner&lt;/strong&gt; that checks a PDF for hidden metadata — author name, GPS coordinates, edit history — before you send it to someone. I didn't know PDFs quietly carried that stuff around until I ran a file through it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this is worth thirty seconds of thought
&lt;/h2&gt;

&lt;p&gt;I'm not going to pretend uploading a random PDF to a free tool is going to ruin your life. Most of the time, nothing bad happens — the file gets processed, deleted, and nobody looks at it. But "most of the time nothing bad happens" is also true of leaving your front door unlocked. It's not really an argument for doing it on purpose, especially when the alternative costs you nothing.&lt;/p&gt;

&lt;p&gt;The next time you're about to drop a resume, a contract, or a scanned ID into a random "free PDF editor" tab, it's worth a beat of thought about where that file is actually going — and whether it needed to go anywhere at all. Increasingly, for basic PDF tasks, it doesn't have to.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you want to try it yourself: &lt;a href="https://www.ihatepdf.cv" rel="noopener noreferrer"&gt;ihatepdf.cv&lt;/a&gt; — free, no watermark, no upload, no signup. I'd genuinely like to hear if it handles your use case; drop a comment.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>privacy</category>
      <category>career</category>
      <category>javascript</category>
    </item>
    <item>
      <title>I Built a 46-Tool PDF Editor That Never Touches a Server. Here's the WASM Architecture Behind It.</title>
      <dc:creator>Pranav</dc:creator>
      <pubDate>Mon, 17 Aug 2026 17:01:25 +0000</pubDate>
      <link>https://dev.to/pranav_503667748505fccf1b/i-built-a-46-tool-pdf-editor-that-never-touches-a-server-heres-the-wasm-architecture-behind-it-2ma2</link>
      <guid>https://dev.to/pranav_503667748505fccf1b/i-built-a-46-tool-pdf-editor-that-never-touches-a-server-heres-the-wasm-architecture-behind-it-2ma2</guid>
      <description>&lt;p&gt;Every "free" PDF tool I've ever used works the same way: you upload your file to a server, a script on the other end does the actual work, and you download the result a few seconds later. That's fine until you remember what people actually put in PDFs — signed contracts, medical records, tax documents, resumes with home addresses on them — and realize you just handed all of it to a company you've never heard of, in exchange for a "merge" button.&lt;/p&gt;

&lt;p&gt;That bothered me enough that I spent the last several months building &lt;a href="https://www.ihatepdf.cv" rel="noopener noreferrer"&gt;ihatepdf.cv&lt;/a&gt;, a PDF toolkit with 46 tools — merge, split, compress, OCR, encrypt, redact, convert to and from almost every format, even a GST invoice generator — where &lt;strong&gt;the file never leaves the browser&lt;/strong&gt;. No upload step exists in the architecture, because there's no server-side processing to upload &lt;em&gt;to&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here's what building that actually looked like.&lt;/p&gt;

&lt;h2&gt;
  
  
  The constraint that shaped everything
&lt;/h2&gt;

&lt;p&gt;The moment you say "no server," you've ruled out the easy path for basically every PDF operation. Compression, OCR, format conversion — these are normally solved with a beefy backend running Ghostscript, Tesseract, or LibreOffice headless. None of that exists in a browser tab.&lt;/p&gt;

&lt;p&gt;So the entire toolkit is built on &lt;strong&gt;WebAssembly modules doing the heavy lifting client-side&lt;/strong&gt;, wrapped in a PWA shell so the app itself works offline after the first load. A few examples of how that split played out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Compression&lt;/strong&gt; — three presets (Light/Medium/Heavy) implemented by re-encoding embedded images and re-serializing the PDF object graph in-browser, rather than shelling out to Ghostscript.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCR&lt;/strong&gt; — Tesseract compiled to WASM, run entirely client-side against scanned pages to produce a searchable text layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Office format conversion&lt;/strong&gt; (Word, Excel, PowerPoint ↔ PDF) — this is normally the hardest thing to do without a server, since it usually means Microsoft's own rendering engine. Getting formatting, merged cells, and embedded fonts to survive the round trip without a backend was the single most time-consuming part of the build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI features&lt;/strong&gt; (chat-with-PDF, summarization) — the one place a network call is unavoidable, since on-device LLMs aren't practical yet for this. Everything else stays local.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The handwriting-to-PDF problem
&lt;/h2&gt;

&lt;p&gt;The tool that took the most iteration was converting handwritten notes into a searchable PDF. My first few attempts ran OCR and dumped the recognized text back onto the page — and it wrecked any document with actual structure: tables, multi-column notes, forms. Text would get recognized correctly but placed in the wrong reading order, or a two-column page would get flattened into one garbled column.&lt;/p&gt;

&lt;p&gt;I went through a few architectures before landing on the right one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tune Tesseract's page segmentation mode (PSM) per document type — no single PSM setting worked for both dense paragraphs and sparse tables.&lt;/li&gt;
&lt;li&gt;Add line-grouping logic to reconstruct reading order from bounding boxes instead of trusting raw OCR output order.&lt;/li&gt;
&lt;li&gt;Add gap-based column splitting to detect multi-column layouts before running line grouping.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of that improved accuracy, but it was still fundamentally fragile — I was trying to &lt;em&gt;reproduce&lt;/em&gt; the original layout from OCR output, which throws away information every time.&lt;/p&gt;

&lt;p&gt;The fix was to stop trying to reconstruct the page at all. The tool now produces a &lt;strong&gt;"searchable scan"&lt;/strong&gt;: the original handwritten image stays exactly as-is as the visual layer, and the OCR'd text sits invisibly underneath it, positioned to match. You see your actual handwriting; Ctrl+F finds the words anyway. It's a much smaller claim architecturally — don't recreate the document, just make it searchable — and it's the version that actually holds up on messy real-world input.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service workers are where PWAs go to die
&lt;/h2&gt;

&lt;p&gt;The offline-first requirement meant getting a service worker right, which is its own genre of pain. The specific bug that cost me the most time was a &lt;code&gt;TypeError&lt;/code&gt; thrown when the SW's cache lookup resolved to &lt;code&gt;undefined&lt;/code&gt; — happening intermittently, only on certain navigation patterns, which made it miserable to reproduce. The fix ended up being a full rewrite of the fetch-handling logic to explicitly guard every cache read instead of assuming a &lt;code&gt;Response&lt;/code&gt; would always come back. If you're building a PWA and haven't hit this yet, you will — write the defensive check before you need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond the privacy pitch
&lt;/h2&gt;

&lt;p&gt;"No upload" is usually pitched as a privacy feature, and it is one. But it's also just a &lt;em&gt;product&lt;/em&gt; advantage that's easy to undersell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works on a plane.&lt;/strong&gt; Once the PWA is cached, there's no network dependency for 45 of the 46 tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There's no file size ceiling imposed by a server timeout or upload limit&lt;/strong&gt; — processing is bounded by the user's own device, not by what a backend is willing to accept.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The infra bill doesn't scale with usage.&lt;/strong&gt; Every PDF operation is a cost on the user's CPU, not mine. That's a very different scaling story than a SaaS with a processing queue.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The tradeoff, to be honest about it: client-side WASM bundles are heavy, and shipping 46 tools' worth of processing code without tanking Core Web Vitals (especially LCP and TBT) has been an ongoing tuning problem, not a solved one.&lt;/p&gt;

&lt;p&gt;If you're curious about the rest of the toolkit or want to see how a specific conversion holds up on your own file, it's live at &lt;a href="https://www.ihatepdf.cv" rel="noopener noreferrer"&gt;ihatepdf.cv&lt;/a&gt; — genuinely free, no watermark, no signup, and your file really doesn't go anywhere. I've also got a running &lt;a href="https://www.ihatepdf.cv/technical-blog" rel="noopener noreferrer"&gt;technical blog&lt;/a&gt; where I document architecture decisions like these in more depth.&lt;/p&gt;

&lt;p&gt;Happy to go deeper on any part of this in the comments — the OCR layout problem in particular I could talk about for a while.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
