Build PDF Expert
YESreplaces $6.67/mosaves $80.04/yrback to the verdict
A desktop application over mature PDF libraries: annotate and highlight, fill and flatten forms, merge, split and reorder pages, redact so the underlying text is genuinely gone, run optical character recognition over scans, and keep every original untouched with an operation log describing what produced each output.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Builds the front end and the tooling.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - installfree
Why Tauri compiles the native shell and runs the library calls.
Get it Install with rustup from rustup.rs, plus the platform packages Tauri lists for your operating system. open ↗
Verify
A Tauri hello world builds and runs - installfree
Why Structural operations and content extraction. Writing either yourself means implementing parts of the PDF specification.
Get it brew install qpdf mupdf, or your package manager. Decide early whether you bundle them or require them, because it affects distribution. open ↗
Verify
qpdf --version and mutool both run - installfree
Why Phase 5 only. Without it, scans stay unsearchable and everything else still works.
Get it brew install tesseract, or your package manager, plus the language data for the languages you need. open ↗
Verify
tesseract --list-langs includes your language - have readyfree
Why Every phase is tested against them: a text document, a scan, an encrypted file, a form and a corrupted file. Testing against one clean PDF proves nothing.
Get it Collect them from documents you already have. Corrupt one deliberately by truncating it. Keep them in a fixtures directory.
Verify
All five are present and each opens or fails with a specific message
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- documents(id, path, pages, encrypted, has_text_layer, imported_at, content_hash) - operations(id, document_id, kind, params_json, output_path, at) · kind is annotate, fill, merge, split, redact, ocr or reorder - annotations(id, document_id, page, kind, rect_json, content, color, created_at) - form_fields(document_id, page, name, kind, value, flattened) · read from the file's own form definition - The operation log is what makes an output auditable: every produced file names the input hash and the operations applied.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
OUTPUT_DIR | required | ~/Documents/PDF Outputs | Where produced files are written. Deliberately never the source directory. |
QPDF_PATH | optional | /opt/homebrew/bin/qpdf | Only needed if qpdf is not bundled and not on PATH. |
TESSERACT_PATH | optional | /opt/homebrew/bin/tesseract | Only needed if Tesseract is not bundled. Recognition is disabled when it cannot be found. |
OCR_MIN_DPI | required | 300 | Below this, recognition accuracy falls sharply and a warning is shown. |
OPERATION_LOG_PATH | required | ~/Documents/PDF Outputs/operations.json | The audit trail linking every output to its input hash and operations. |
The build, in order
Open anything, and know what you opened
Real PDFs render, including the broken ones, and you can describe what each file actually is.
Render on demand rather than eagerly. A large document must open immediately and fill in as you scroll.
Files
src/render.tsterminalnpm create tauri-app@latest npm install pdfjs-dist
Text layer, encryption, forms, page count and structural damage. Each one changes which operations are possible.
Files
src/inspect.tsA scan, an encrypted file, a form, a very large document and something corrupt. These are your fixtures for every later phase.
Files
fixtures/
done when · tick each as it passeswatch out- A scanned PDF and a text PDF look identical on screen and behave completely differently: search finds nothing, selection selects nothing, and redaction cannot remove text that is not there. Detect the absence of a text layer at import and say so, rather than letting the user discover it when a redaction quietly does nothing.
Annotation that other readers can see
Highlights and notes are real PDF annotations, not a private overlay.
Use the specification's annotation types rather than drawing into the page content. This is what makes them portable and editable elsewhere.
Files
src/annotate.tsRead the original, write a new file, record the operation. Checksum the input before and after as a test.
Files
src/pipeline.tsOpen the output somewhere else. If your annotations are invisible there, they are not annotations.
done when · tick each as it passeswatch out- Storing annotations in your own sidecar database and drawing them at render time produces a document that is blank for everyone else. Write them into the PDF as annotation objects, then verify by opening the output in a different reader, which is the only test that matters.
Forms
You can fill a form and produce a version nobody can un-fill.
Field names, types and current values come from the document. Never infer a form from visual layout.
Files
src/forms.tsTwo outputs: filled and editable, or flattened and final. Make the difference explicit in the interface.
Files
src/forms.tsInspect the output for remaining field objects with qpdf rather than trusting that it looks right.
terminalqpdf --json out.pdf | grep -c AcroForm
done when · tick each as it passeswatch out- A filled but unflattened form still carries editable field values, so a recipient can change what you entered and the change is invisible in most viewers. If the document is going to anyone else, flatten it, and make that the prominent option rather than an advanced one.
Pages, merging and redaction that is real
You can restructure documents, and a redaction actually removes the text.
Merge, split, rotate and reorder. It handles the page tree correctly, which hand-written manipulation does not.
Files
src/pages.tsterminalqpdf --empty --pages a.pdf b.pdf -- merged.pdf
Delete the text objects in the region from the content stream, then draw the black box. Order matters and only one order is correct.
Files
src/redact.tsExtract text from the output and assert the redacted string is absent. Make this an automated test, because it is the one that protects people.
Files
test/redact.test.tsterminalpdftotext redacted.pdf - | grep -c "secret"
done when · tick each as it passeswatch out- A black rectangle drawn over text leaves the text in the file, selectable and extractable, and this has caused real disclosures in published legal and government documents. Redaction must remove the underlying content and then rasterise or rewrite the region. The test is text extraction on the output, not a visual check.
Optical character recognition for scans
A scanned document becomes searchable without its appearance changing.
Check effective resolution and correct skew first. This does more for accuracy than any Tesseract setting.
Files
src/ocr.tsText positioned over the image in invisible render mode, so appearance is unchanged and selection works.
terminaltesseract page.png out pdf
Per page. A low score is information the user needs before relying on a search result.
Files
src/ocr.ts
done when · tick each as it passeswatch out- Recognition quality depends heavily on resolution and skew. Below roughly 300 dots per inch, accuracy falls off sharply, and a skewed scan compounds it. Deskew and check the effective resolution before recognising, and report low confidence rather than presenting a bad result as a good one.
Batch, audit and distributionproduct builder
Repeated work runs unattended and every output can be traced to its input.
A named chain applied to new arrivals, waiting for the file size to settle before processing.
Files
src/batch.tsExtraction test per file. A failure fails the job rather than producing a quiet mistake.
Files
src/batch.tsPlatform signing for distribution. Document that documents never leave the machine.
Files
README.md
done when · tick each as it passeswatch out- A batch that redacts must never be trusted without verification, because a redaction that silently failed produces a file that looks correct and is not. Run the extraction test on every batch output and fail the job loudly rather than writing a file that passes a visual check.
That is the whole plan for PDF Expert. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- The proprietary rendering engines and the files only they handle correctly.
- Cross-device sync and mobile continuity.
- Legally recognised signatures with identity verification.
- Full content editing of arbitrary documents.
- native Apple polish, sync, reliable rendering, and mobile continuity
- pixel-perfect proprietary PDF engine
- identity verification
- qualified trust services
- large template and integration ecosystem
- Bates numbering for legal work, which is a small feature with a devoted audience
- Comparing two versions of a document and highlighting differences
- A command line interface over the same operation chains
Need the files? The project pack on the verdict page hands your agent the whole brief · more documents & pdfs.