<?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: Mitesh</title>
    <description>The latest articles on DEV Community by Mitesh (@mithomania).</description>
    <link>https://dev.to/mithomania</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%2F4063020%2F1a3b369a-7760-43cb-b09e-68e15a108f54.png</url>
      <title>DEV Community: Mitesh</title>
      <link>https://dev.to/mithomania</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mithomania"/>
    <language>en</language>
    <item>
      <title>How I built 15 PDF tools that never upload your files (100% in the browser)</title>
      <dc:creator>Mitesh</dc:creator>
      <pubDate>Tue, 04 Aug 2026 19:43:55 +0000</pubDate>
      <link>https://dev.to/mithomania/how-i-built-15-pdf-tools-that-never-upload-your-files-100-in-the-browser-4n9e</link>
      <guid>https://dev.to/mithomania/how-i-built-15-pdf-tools-that-never-upload-your-files-100-in-the-browser-4n9e</guid>
      <description>&lt;p&gt;A few months ago I needed to merge two bank statements and password-protect the result. Every "free online PDF tool" I found wanted me to upload those files to their servers first. For a document full of account numbers, that felt completely wrong — I have no idea what happens to a file after it's uploaded, how long it's kept, or who can see it.&lt;/p&gt;

&lt;p&gt;So I built the thing I actually wanted: &lt;strong&gt;&lt;a href="https://pdfwithme.com" rel="noopener noreferrer"&gt;PDF WithMe&lt;/a&gt;&lt;/strong&gt;, a set of PDF tools where your files never leave your device. Everything runs in your browser — no upload, no server, no account. Here's how it works and what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core idea: no backend at all
&lt;/h2&gt;

&lt;p&gt;The design flips the usual model. Instead of "send your file to my server, I process it, I send it back," the browser does 100% of the work. Your PDF is read, edited, and saved entirely on your own machine. Nothing is transmitted anywhere — and that single decision (no backend) shaped everything else in a good way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;

&lt;p&gt;Modern browsers are far more capable than people give them credit for. Almost everything I needed already existed as a JavaScript or WebAssembly library:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://pdf-lib.js.org/" rel="noopener noreferrer"&gt;pdf-lib&lt;/a&gt;&lt;/strong&gt; handles the structural work — merging, splitting, rotating, reordering and removing pages, page numbers, watermarks and signatures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://mozilla.github.io/pdf.js/" rel="noopener noreferrer"&gt;pdf.js&lt;/a&gt;&lt;/strong&gt; (Mozilla's PDF engine) renders pages, which powers PDF-to-image conversion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://qpdf.sourceforge.io/" rel="noopener noreferrer"&gt;qpdf&lt;/a&gt; compiled to WebAssembly&lt;/strong&gt; does real &lt;strong&gt;AES-256 encryption and decryption&lt;/strong&gt; — that's what lets you password-protect a PDF, or remove a password from one you own, right on your device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://tesseract.projectnaptha.com/" rel="noopener noreferrer"&gt;Tesseract.js&lt;/a&gt;&lt;/strong&gt; (also WebAssembly) runs OCR to pull text out of scanned documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://stuk.github.io/jszip/" rel="noopener noreferrer"&gt;JSZip&lt;/a&gt;&lt;/strong&gt; bundles multiple outputs (like split pages) into one download.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;WebAssembly is the quiet hero. qpdf and Tesseract are mature C/C++ projects; compiling them to WASM means desktop-grade capabilities in a browser tab, with zero install and zero server.&lt;/p&gt;

&lt;h2&gt;
  
  
  A nice side effect: it works offline
&lt;/h2&gt;

&lt;p&gt;Because there's no server to call, the app doesn't actually &lt;em&gt;need&lt;/em&gt; the internet after it loads. A service worker precaches the app and its libraries, so it's a PWA — turn off your Wi-Fi, merge a PDF, and it just… works.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-offs (it's not all free)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory is the limit.&lt;/strong&gt; A server can stream a huge file; a browser tab holds it in RAM, so very large PDFs are constrained by the device.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bundle size.&lt;/strong&gt; WASM binaries aren't tiny, so I lazy-load each tool's dependencies only when you open that tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some problems are genuinely hard client-side.&lt;/strong&gt; PDF-to-Word is the best example — reconstructing editable layout is messy, so I ship two modes: a best-effort "editable" rebuild, and an "exact look" fallback that drops each page into Word as an image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why it was worth it
&lt;/h2&gt;

&lt;p&gt;Beyond privacy — which is why I started — no backend has lovely properties: nothing to run so it costs almost nothing to keep online, no database of user files to breach or subpoena, and "your files never leave your device" isn't a slogan I have to defend, it's just how the architecture works. You can verify it by watching your network tab.&lt;/p&gt;

&lt;p&gt;If you want to try it, it's free with no sign-up: &lt;strong&gt;&lt;a href="https://pdfwithme.com" rel="noopener noreferrer"&gt;pdfwithme.com&lt;/a&gt;&lt;/strong&gt;. It's early, so I'd genuinely love feedback — on the tools, the client-side approach, or what to build next.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

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