Most "free online PDF" sites upload your file to a server. I wanted the opposite: a toolkit where the file never leaves the device. That constraint changes almost every implementation decision.
Why browser-only is harder than it sounds
PDF manipulation is CPU-heavy. Doing it on the main thread freezes the UI for seconds on a 40-page document. The fix is to push every operation into a Web Worker:
const worker = new Worker('/assets/pdfOps.worker.js', { type: 'module' })
With pdf-lib inside the worker, merging and splitting stay responsive. The trade-off is that you can no longer touch the DOM from the parsing code, which forces a clean message-passing boundary.
Compression is the part nobody warns you about
There are two very different kinds of "compress a PDF":
- Lossless-ish: re-encode streams, drop unused objects. Text stays selectable. Savings are modest, often 10-30%.
- Rasterise: render each page to an image and rebuild the PDF. Savings can be 80%+, but you lose selectable text, links and accessibility.
Most tools quietly do (2) and call it compression. If a document needs to stay searchable or screen-reader friendly, that is a real regression. The honest approach is to expose both and say which is which.
Archive handling
ZIP is easy (JSZip). RAR and 7Z are not - they need dedicated decoders, and doing it in the browser means shipping a worker bundle measured in hundreds of kilobytes. Worth it only if archive extraction is a core feature rather than a checkbox.
What I ended up with
A static single-page app: no upload endpoint, no account system, no server-side file handling. Everything runs client-side, so "we delete your file" is not a promise - there is nothing to delete.
If you want to see the result, it is at FileCPU - free, no signup, and it covers PDFs, images and archives.
The main lesson: when you remove the server, you inherit the performance budget. A worker-based design is not an optimisation, it is the only way the thing is usable.
Top comments (0)