DEV Community

K Merchant
K Merchant

Posted on

How I built a PDF editor with zero backend

Every PDF editor you've ever used has a server. You upload your document, it gets processed somewhere you can't see, and a modified file comes back. For tax returns, legal contracts, and medical records, that's a strange thing we've all agreed to.

I kept wondering: how much of a PDF editor actually needs the server? Turns out, almost none of it. So I built one with zero backend. No API, no database, no auth, no analytics. Just static files. Here's how.

The core realization

A PDF is a structured document format, not magic. Rendering it means parsing objects and painting them to a canvas. Editing it means rewriting those objects and re-serializing the file. Every step of that is computation, and browsers are extremely good at computation now. The server was never doing anything the client couldn't do — it was just where developers found it convenient to put the code.

Going serverless wasn't a cost decision. It was the product. If there is no server, there is nothing to breach, subpoena, or monetize. Privacy becomes a property of the architecture instead of a promise in a privacy policy.

The architecture

The app is a static site. index.html, some JS, some CSS. That's the entire deployment. Here's what happens inside:

Rendering. Pages render to <canvas> elements at the device's pixel ratio. There's no text-selection layer — pages are canvas-only with selection disabled to keep touch annotation reliable; the edit tool locates text through its own hit-testing of the content stream instead. Zoom is re-rendering at a higher scale, not image stretching, so text stays sharp.

Editing real text. This is the part most "PDF editors" fake. Many tools let you click on text and type, then export a PDF with your new text drawn on top of the old text — the original bytes are still in the file. Select the text underneath, or extract it programmatically, and the old content is right there.

PDF Studio rewrites the page's content stream on export. When you edit a paragraph, the old text-showing operators are replaced and the file is re-serialized without the original bytes. Old content is gone, not covered up — for text the document's encoding can represent, which is the overwhelmingly common case. (Edge case, stated plainly: replacements in scripts the original font can't encode fall back to painting over the old text.) This distinction matters enormously for redaction (more on that in a moment) and it's the difference between editing a PDF and annotating a screenshot of one.

Forms. The app parses AcroForm field definitions, renders fillable inputs over the page, and on export can either keep fields live or flatten them into static page content. Flattening matters when you're sending a form to someone who shouldn't be able to change the answers.

Redaction, done honestly. A lot of redaction tools draw a black rectangle over sensitive text and call it done. The text is still in the file — anyone can select it, copy it, or extract it. Proper redaction means removing the text from the content stream entirely and burning the black box into the rendered page. That's what this does: the export contains no trace of the redacted content. I wrote a separate guide on verifying this (linked at the end), because "trust me" is not a redaction strategy.

OCR on-device. Scanned PDFs get OCR through a WebAssembly build of Tesseract running in a Web Worker, so the UI never blocks. The language data downloads once and caches locally. Your scanned document never leaves the machine — which is the entire point, since scanned documents are disproportionately the sensitive kind (signed contracts, IDs, medical forms).

State and undo. All document state lives in memory with a full undo/redo stack, and the app quietly autosaves your session to your own browser's local storage — never a server — so you can pick up where you left off. Export is just the browser downloading a file it built locally, and one click wipes the saved session from the device entirely.

The hard parts

Memory. A 200-page PDF with embedded fonts can eat serious RAM when every page holds a canvas. The discipline so far: cap render resolution, cancel stale render tasks the moment you zoom, keep per-page work cheap. Full viewport culling — only rendering pages near the visible area — is still on the roadmap. Mobile forced this discipline — phones have no patience for desktop memory habits.

Text editing fidelity. Replacing text in a content stream while preserving the surrounding layout means understanding the text-showing operators, the font encodings, and the positioning math. PDFs position glyphs with explicit coordinates, not flow layout. Editing a line of text is closer to surgery than word processing: you remove the old showing operations, compute where the replacement goes in the same coordinate space, and write new operations that the next renderer will interpret identically.

Mobile. The recent overhaul was the biggest single chunk of work. Touch-based annotation, dialogs that fit phone viewports, a top bar that scrolls internally instead of overflowing the page at tablet widths. Sixteen markup tools had to work with fingers, not cursors. The lesson: mobile isn't a smaller desktop, it's a different input paradigm, and every interaction needs rethinking.

The service worker trap. The app works offline via a service worker, which is great for users and terrible for developers: during testing I repeatedly "verified" fixes against a stale cached bundle. If you ship an offline-capable app, build bundle-hash verification into your QA process or you will chase ghosts.

What I'd do differently

I'd have designed the export pipeline around incremental saves earlier. Right now export re-serializes the whole document, which is fine for typical files but wasteful for 500-page reports where you changed one word. That's the next architectural project.

Try it / tear it apart

It's free and MIT-licensed: https://navigatorslab.com/pdf-studio/
Source: https://github.com/Kayforkind/NavigatorsLab-PDF-Studio

No signup, no tracking — there's genuinely nothing to sign up for. If you find a PDF it chokes on, that's the most useful bug report you can file.

The verification guide: https://dev.to/kayforkind/how-to-properly-redact-a-pdf-so-the-text-is-actually-gone-5alf

Top comments (0)