Skip to content

Latest commit

 

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Deckle

PDF tools that never upload.

Free, open source, and entirely client-side — without your file ever leaving your device, because Deckle has no server to send it to.

Working today: merge · split · reorder, rotate and delete pages · compress · OCR · redact · fill forms · sign · compare · batch · PDF to images · images to PDF · password protect · watermark · page numbers · privacy scrub · edit text (Beta).

Status: early but real. Every feature listed above is covered by tests that run on each commit. The rest is being built in phase order — see phases.md.

OCR is worth spelling out, because it is the feature most people assume must involve a server: text recognition runs in a WebAssembly build of Tesseract inside a Web Worker on your own machine. The 2.9 MB language model is served from Deckle's own origin the first time you use it, and never from a third party.

Redaction actually redacts

Most "free" redaction tools draw a black rectangle over the text. The words are still in the file — select-and-copy recovers them, and so does any PDF parser. That is how people leak the exact thing they were trying to hide.

Deckle deletes the text from the page's content stream, then draws the box. You do not have to take our word for it: the redacted page is written uncompressed, so you can open the output in a text editor and confirm the words are gone. There is a test suite that does exactly this on every commit (tests/unit/redact.test.ts), and it decodes hex-encoded strings before checking — a naive search for the secret would find nothing whether or not redaction worked, which is precisely how fake redaction passes a careless test.

Scans get the same treatment. When the marked area falls on an image, Deckle decodes that image, paints the region black, and re-encodes it — the pixels are replaced, not covered. The test for this pulls the JPEG back out of the saved file, decodes it, and counts black pixels, because a test that only looked at the page would pass just as happily on a black rectangle over an untouched photograph.

Where it can't do that — an image encoding Deckle cannot decode, or an inline image whose pixels live in the page itself — it says so and tells you to treat the area as unredacted, rather than drawing a box and implying the job is done.

Editing the words on a page, honestly

Click any line of text to see what drew it — the font, the size, the colour, straight out of the page's content stream — and change it if you want to.

This is labelled Beta and it stays labelled Beta, because real PDF editing is harder than any tool's marketing admits. A document that embeds its own font embeds only the glyphs its words needed, so there is often no letter "q" available to type. Deckle sets replacement text in the nearest standard face and tells you, per edit, that the shapes will differ. Text too wide for the space it replaces is shrunk to fit, down to 60% and no further, and then it says it will overlap. Characters the standard fonts cannot write — Japanese, Cyrillic, Greek — are refused outright, with the original left exactly as it was.

Nothing is written out quietly wrong. That is the entire design.

Filling a form without handing it over

The forms people are asked to fill in are the ones they should least want to upload: tax returns, medical intake, employment paperwork, bank onboarding. Every free filler online takes the document to a server first.

Deckle reads the form's fields and shows them as ordinary inputs — a text box is a text box, a dropdown is a dropdown — so it works on a phone, and what you see on screen is exactly what gets written to the file. Fields the document locked stay locked. Values it cannot write are listed with the reason, never dropped quietly. Flattening is a checkbox, and it says what it does: the answers are baked into the page and nobody can change them afterwards, including you.

Password protection, and an honest note about permissions

Set a password with AES-256, or remove one you have. This is the only feature with a second PDF engine behind it — qpdf, compiled to WebAssembly, running in the same tab as everything else.

The permission checkboxes — printing, copying, editing — are labelled in the app as requests rather than locks, because that is what they are. The encryption is real; whether a reader honours "no printing" once it has the password is up to that reader, and several ignore it. Tools that imply otherwise are selling something.

The other half of the honesty: Deckle cannot recover a lost password. There is no server holding a copy and no reset link. That is the same property that makes it safe.

Both directions between PDFs and images

Export every page as PNG or JPG at 72 to 600 DPI, zipped, named so they sort in reading order — report-002.png, not report-2.png, which sorts after report-10.png in every file manager.

Going the other way, drop in images and get a PDF. Phone photos come out the right way up, because the EXIF orientation tag is read rather than ignored. PNG and JPG embed directly; HEIC and WebP are decoded by your own browser first, so no extra decoder ships and nothing is uploaded to convert them.

Signing, without pretending to be more than it is

Draw a signature with a mouse, trackpad, or finger; type your name in a script face; or upload a photo of your signature on paper — the paper gets keyed out so only the ink lands on the page. Then drop it where it goes and save.

What Deckle produces is a visual signature: a picture of your signature flattened into the page, the same as signing a printout and scanning it. It is not a cryptographic digital signature. It carries no certificate, proves nothing about who signed, and cannot show whether the document was altered afterwards. For most agreements that is exactly what is wanted, and it is what DocuSign's free tier gives you too — but if someone has asked you for a digitally signed PDF, this is not that, and the app says so on the screen rather than in the small print.

Comparing two revisions

Drop in two versions of a contract and Deckle shows them side by side with what changed marked on the pages: text added, text removed, a clause that moved, and — separately — a page that says exactly the same thing in a different layout.

Two details make the difference between a useful comparison and a wall of red. Pages are matched by content, so inserting a page does not report every page after it as rewritten. And a moved paragraph is reported as a move rather than as a deletion plus an unrelated insertion, even when new text was written right next to where it landed.

Draftable charges for this.

Batches, uncapped

Point Deckle at a folder and run one operation over everything in it — compress, watermark, number the pages, or strip hidden data. Results come back as a zip.

Files are processed one at a time, deliberately: parallel workers on large scans is how a browser tab runs out of memory, and there is nothing to win, because the work is CPU-bound either way. One failure does not end the run — that file is reported as failed and left alone, never replaced with a broken copy, and the zip contains everything that succeeded.

Two files called invoice.pdf from different folders both survive, numbered the way your desktop numbers them. An archive that silently keeps one of them is data loss reported as success, so there is a test for it.

It tells you what your PDF is carrying

PDFs hold things you cannot see: who wrote them, what software produced them, JavaScript that runs when the file opens, actions that fetch a URL, and earlier revisions of the document. A PDF really can phone home, and no consumer tool exposes that for free.

Deckle's scrubber shows you the findings before removing anything — "this file contains embedded JavaScript, an action on open, and 1 external link" — then lets you choose what to strip. The report is worth as much as the cleaning.


Why this exists

Every mainstream "free" PDF tool uploads your file to someone else's machine.

  • iLovePDF, Smallpdf, PDF2Go — your file goes to their servers, the free tier is throttled to 1–2 operations a day, and files are capped at 5–25 MB.
  • Adobe Acrobat Pro — $240 a year, and in-place text editing is a flagship paid feature.
  • Draftable — charges for comparing two PDFs.
  • DocuSign / HelloSign — charges for what is, for a solo user, drawing on a page and flattening it.

For a legal contract, a medical record, or a bank statement, "we'll just upload it" is a real problem. Plenty of workplaces block these sites outright for exactly that reason.

Deckle does the same jobs with the file staying on your machine.

How it compares

iLovePDF free Smallpdf free Acrobat Pro ($240/yr) Deckle
File stays on your device No No Yes Yes
Merge / split / organize Limited per day Limited per day Yes Unlimited
File size cap ~25 MB ~5 MB None None
Compress Limited Limited Yes Unlimited (JPEG images, ~85% on a scan)
OCR Paid Paid Yes Free
True redaction Paid Paid Yes Free
E-signature Paid Paid Yes Free (visual, not cryptographic)
Compare two PDFs No No Yes Free
Fill and flatten forms Limited per day Limited per day Yes Unlimited
PDF ↔ image Limited per day Limited per day Yes Unlimited
Password protect / remove Limited per day Limited per day Yes Free (AES-256)
Batch, uncapped Paid, capped Paid, capped Capped Free
Strip embedded JS / trackers No No Partial Free
In-place text edit No No Yes Free (Beta, with stated limits)
Works offline No No Yes Yes (installable, one button)
Account required Yes Yes Yes No

Items marked planned are on the roadmap in phases.md, in build order. This table will be updated as each ships — not before.

How the privacy guarantee is enforced

"We don't upload your files" is easy to claim. Deckle enforces it in four places:

  1. There is no backend. Not a stub, not a serverless function. The deployment is static files on a CDN. There is nowhere for a file to go.
  2. A Content Security Policy in index.html sets connect-src 'self', so the browser itself blocks any request to a third-party origin.
  3. A runtime tripwire (src/core/guard/network-tripwire.ts) patches fetch, XMLHttpRequest, WebSocket, EventSource, and sendBeacon to throw during development, so an accidental network call fails loudly instead of shipping quietly.
  4. A CI test (tests/e2e/zero-network.spec.ts) runs every operation against real PDFs and fails the build if a single network request is made during processing.

There is also a lockfile check (scripts/check-deps.mjs) that fails CI if any analytics or error-reporting package appears in the dependency tree, including transitively.

One honest caveat: connect-src is 'self', not 'none', because the app's own JavaScript and (later) its WASM and OCR language data load from Deckle's own origin on first visit. Nothing ever reaches a third party, and once the service worker lands (M11) repeat visits fetch nothing at all. Claiming "zero requests, ever" would be false on first load, and we would rather state the nuance than have you find it.

About file size

Deckle sets no size limit, no page limit, and no daily quota. There is still a real ceiling — your browser tab's memory — and we would rather give you the number than pretend it doesn't exist.

Measured on Node 24 (scripts/benchmark-memory.mjs): a merge needs roughly 12.6 KB of memory per page. The surprise is that this tracks page count, not file size. A 500 MB scanned document with 500 pages is comfortable; a 40 MB text document with 30,000 pages needs about 390 MB and takes 86 seconds.

So Deckle warns you based on page count, with the actual estimate in megabytes, and never blocks you. Browser-side figures are still to be measured and will be published here when they are.

What Deckle will never have

  • A backend, of any kind
  • Telemetry, analytics, or error reporting
  • AI features (every implementation means sending your document to someone's server)
  • Accounts, email walls, or daily limits
  • Watermarks on your output

These are written down as numbered, enforceable rules in rules.md.

It works with the network unplugged

Deckle installs as an app and runs with no connection at all. One button saves the heavy parts — the OCR language model and the encryption engine — and after that every tool works offline, including OCR and password protection.

That is a button rather than something that happens on first visit, because those payloads are about 17 MB and most people never touch either feature.

There is a test for the claim rather than a promise: tests/e2e/offline.spec.ts switches the browser offline, reloads, and then merges documents and runs OCR.

Running it

npm install
npm run fixtures
npm run dev

Some tests need a realistic multi-megabyte scanned PDF, which is generated rather than committed:

npm run fixtures:scan

Other commands:

npm test              # unit tests (Node, no browser needed)
npm run test:e2e      # zero-network + end-to-end tests
npm run typecheck     # TypeScript
npm run lint          # ESLint
npm run check:deps    # fail if a telemetry package is in the lockfile
npm run build         # static output in dist/

Self-hosting

npm run build produces a dist/ folder of static files. Serve it from anything — Cloudflare Pages, Netlify, nginx, an internal file share, or a USB stick. There is no backend to run, no database to provision, and no environment variables to set.

For a machine with no network at all:

npm run release:zip

That writes deckle-offline-<version>.zip — the app, the OCR model, the WASM, and a 90-line dependency-free static server. Unzip it anywhere and run node serve-offline.mjs.

One honest note on that: opening index.html as a file:// URL does not work, and the zip says so. The page loads and then does nothing, because every operation runs in a Web Worker and browsers refuse to start a worker from a file:// origin. Hence the tiny server, which binds to localhost, serves only its own folder, and reaches the network never.

This is also why the hosted version stays free at any scale: the host serves a couple of megabytes once, the visitor's own CPU does all the work, and a traffic spike costs nothing.

Deploying your own copy

DEPLOY.md walks through putting this on Cloudflare Pages, step by step, assuming no prior knowledge. It is free, needs no card, and takes about ten minutes — most of which is waiting for a build.

Contributing

Read CLAUDE.md first — it points at the four documents that define the project, in reading order. In particular, rules.md contains hard invariants; a change that breaks one of them will not be merged, regardless of how useful the feature is.

License

MIT. Vendor it, fork it, ship it inside your company. That is the point.

About

Free, 100% client-side PDF toolkit — merge, split, compress, OCR, redact, sign, compare, and edit PDFs entirely in your browser. Your files never leave your device.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages