# Every PDF, an Electron shell wrapped around a Python PDF backend

> Every PDF is a desktop application that combines a Next.js renderer, an Electron main process and a Python FastAPI backend to cover editing, conversion, splitting, merging, watermarking and encryption of PDF files. The interesting engineering is in the packaging: a per-platform Electron Builder pipeline, a Python virtual environment assembled by a Node script, and a macOS code signature change that broke the auto-updater for every earlier version.

**DDULDDUCK/every-pdf** — ✍️ A powerful, all-in-one desktop PDF toolkit to edit, convert, merge, and secure your documents. Built with Electron, Next.js, and Python.

- Repository: https://github.com/DDULDDUCK/every-pdf
- Website: https://github.com/DDULDDUCK/every-pdf/releases
- Stars: 1,254 · Forks: 90
- Language: TypeScript
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/dduldduck-every-pdf

## Three processes, one window

Every PDF is built with Nextron, which is the framework that puts Next.js and Electron together, and it adds a third piece: a Python backend served with FastAPI. The frontend is React with TypeScript and Tailwind CSS, the main process is TypeScript, and the backend is Python. Packaging is handled by Electron Builder.

The project structure in the README shows how those pieces are laid out, and the directory names are the architecture:

```
every-pdf/
├── app/          # Final Electron app resources (built by Nextron)
├── backend/      # Python backend source and virtual environment (venv)
├── main/         # Electron main process source (TypeScript)
├── public/       # Static assets (images, etc.)
├── renderer/     # Next.js frontend source (React, TypeScript)
├── resources/    # Resources used during build (e.g., app icons)
├── scripts/      # Build/development automation scripts
```

The split has a consequence that is worth understanding before you install anything. The Python side is not a remote service, it is a local process, and it lives in a virtual environment inside the backend directory, created and populated by a Node script during setup. The package manifest confirms the arrangement: the main entry point is app/background.js, and the development and build scripts all run a step that sets the backend up before anything else happens.

So the application ships a Node runtime, an Electron runtime and a Python interpreter. That is a heavy footprint for a document utility, and it is the price of using a mature Python PDF toolchain inside an interface built with React rather than shipping a native desktop binary.

## The feature list is a utility belt, not a page-layout engine

The features are the seven things people repeatedly need to do to a PDF, and the order in the list tells you how the application is organised.

The PDF editor is marked as new and covers adding text, signatures, images and checkboxes, which is the phrasing to notice: the editor places elements onto a document rather than reflowing the content of one. The other entries are file operations. Convert handles PDFs to other formats and other formats to PDFs. Split Pages divides a document by a page range or by individual page numbers. Merge Files combines documents with a drag-and-drop. Watermark adds a custom text or image watermark. Manage Pages rotates and reorders pages. Encrypt and Decrypt adds or removes password protection.

Six of the seven are operations on files rather than on the document's structure, and the seventh adds layers to a page. That is a coherent scope for a utility application, and it is also the boundary: a layout tool that reflows text, rebuilds paragraphs and re-typesets a page is a different class of software, and the feature list does not claim it.

The PDF editor arriving as a new feature in the 2.0 line is the one place where the scope did widen, since signature placement and checkboxes turn the app from a file-shuffler into something you can complete a form with. The demos in the README are for the new editing features from v2.0.0 and for the split feature, which is a reasonable sample of where the effort went.

## The dev loop starts the frontend and the backend together

The setup instructions are four commands, and the developer prerequisites are Node.js v18 or higher, Python v3.10 or higher, and Git:

```bash
git clone https://github.com/DDULDDUCK/every-pdf.git
cd every-pdf

npm install
npm run setup-backend
npm run dev
```

The comment on the setup step says it is automatic: the script creates a virtual environment and installs the dependencies. That is scripts/setup_venv.js, run by the setup-backend script, and it is the point where the Python half of the project is materialised on your machine.

The dev script is the part that explains the shape of the project. It runs a copy-pdf-worker step, then the backend setup, and then starts the frontend and the backend concurrently. The frontend is Nextron, which is the Next.js development server wrapped for Electron. The backend is a separate Python invocation, changing into backend/src and running the pdf_processor module with the interpreter from the virtual environment:

```bash
npm run dev:frontend
cd backend/src && ../../backend/venv/bin/python -m pdf_processor
```

There is a separate script for Windows, dev:backend:win, which differs only in the path to the interpreter, since the virtual environment lives under Scripts rather than bin there.

The copy-pdf-worker step is the one that is not explained in the README, and it is worth noticing for a different reason: the scripts are named for what they do, so a reader of the manifest can tell that a PDF worker binary or file has to be placed into the frontend before development starts. The build script runs the same chain, so the artifact is in place for production builds too.

## Three build targets and one publish pipeline

The build and release scripts in the package manifest are per platform, and each one repeats the same three steps before invoking Nextron: set the backend up, build the backend, then build the Electron app. There are targets for Windows, macOS and Linux, and a matching set of publish targets that run the build and then hand the result to Electron Builder with the publish flag set.

```bash
npm run build:win
npm run build:mac
npm run build:linux
```

The Windows build asks Nextron for a win and x64 build, and the macOS one for a mac and universal build, so the macOS artefact is a universal binary. The Linux one is left as a plain linux target without further flags.

The configuration for all of this lives in electron-builder.yml at the repository root, and the manifest declares the package as private, which is consistent with a project that distributes through GitHub releases rather than through a registry. The releases page is the stated homepage of the project, and the README's download table points at the latest release for each platform.

There is also a clean script that removes the virtual environment and the backend build directories, and a postinstall hook that runs electron-builder install-app-deps, which is the standard way of making native modules match the Electron runtime. That hook matters in an application with a Python side, because the native dependencies of the PDF stack have to line up with the packaged runtime as well as the development one.

## The macOS signature change that broke every earlier build

The first thing in the README is a warning, and it is the most useful thing in the file for anyone running the application.

The official code signature was updated to enhance the security of the application, and as a result the auto-updater will fail for all previous versions. The instruction is that you must manually download and install v2.0.2 or later to receive the update, with an apology for a one-time inconvenience and a promise that future updates will be delivered automatically as expected.

This is a deployment detail that every desktop application on macOS eventually meets, and it is worth understanding rather than just obeying. The auto-updater on macOS validates the update against the signature of the running application, so changing the signing identity, or re-signing a build with a different certificate, produces an application that can no longer update itself. The old versions have not broken because of a bug in the updater; they have broken because the thing they trust has changed.

The consequence for a user is a manual download, and the consequence for a maintainer is that the release pipeline and the signing identity are part of the same system. The README's framing, that this is a one-time inconvenience, is the usual way such a thing is presented, and the v2.0.2 threshold tells you exactly where the break happened.

For anyone evaluating the project, this is also a signal about the release cadence. Versions 2.0.6, 2.0.8 and 2.1.0 were published in March and May 2026, so the project is shipping, and the signing change landed in the middle of that sequence rather than at the start.

## Two READMEs, a Korean original and an English translation

The repository carries a README.md and a README.ko.md, and the badge row links to each with a language label for English and Korean. The pull requests, issue tracker and contributors sections are all referenced from the badge row as well, and the contributor list is generated in the all-contributors format, with the .all-contributorsrc file at the root holding its configuration.

The rest of the project furniture is conventional: a CHANGELOG.md, a CONTRIBUTING.md that the README points to for details, an electron-builder.yml, a tsconfig.json, a .vscode directory, a scripts/ directory, an asset/ directory and a resources/ directory for the build-time resources such as the application icon.

The documentation is thin in one respect that matters. The README covers features, downloads, the developer setup and the project structure, and it stops there. There is no architecture document, no description of the HTTP interface the FastAPI backend exposes to the renderer, and no explanation of what the PDF worker is or where the PDF processing actually happens. The main/ and backend/ directories will tell you, but the reader is expected to read the code.

For an open source desktop application maintained with a two-language documentation setup, that is a reasonable balance, and the presence of a Korean README alongside the English one indicates an active local community around the project rather than a single-maintainer hobby.

## Where Every PDF is the wrong tool

Three limits are visible in the documentation rather than guessed.

The first is platform coverage. The download table lists Windows with an .exe and macOS with a .dmg, and the Linux row with an .AppImage is present but commented out in the source. A Linux build target exists in the npm scripts, but the project does not publish a Linux artefact for download, so a Linux user has to build it themselves. For a tool whose whole appeal is being a download and double-click, that is a real gap.

The second is the shape of the application. Everything is arranged around an interactive window with a Next.js renderer, an Electron process and a Python service, and that is a good fit for a person at a desk. It is a poor fit for a script that converts a hundred files, or for a server-side pipeline, because there is no documented command line or API surface. The backend does speak HTTP over FastAPI, but the README does not describe that interface, so treating it as a service means reading the code first.

The third is the cost of the approach. A download that carries a Node runtime, an Electron runtime and a Python interpreter with a virtual environment is a large install, and the update story has already had one break caused by a signing change on the maintainer's side. Users who need only to split, merge or encrypt a document have command line tools that do the same job with none of that footprint, and a user who needs the editing features is the one for whom this application earns its size.

## Conclusion

Every PDF fits a Windows or macOS user who wants the common PDF operations in one window without a command line, and the source is a readable reference for a three-process desktop application that mixes a Node toolchain with a Python service. It does not fit a Linux desktop user, since the Linux download row is commented out in the README even though a Linux build target exists, and it does not fit a server-side or automated pipeline, because everything is arranged around an interactive window. Before depending on it, check the release you install, because the macOS code signature change means anything older than v2.0.2 cannot be updated automatically, and expect the install to be a download rather than a package manager entry. The licence is MIT, v2.1.0 was published on 2026-05-17, and the last push was on the same day.

## FAQ

### How do I install Every PDF?

From the releases page of the repository. The README lists a Windows .exe and a macOS .dmg, with the Linux .AppImage row commented out, so there is no published Linux download even though a Linux build target exists in the npm scripts.

### Why does the macOS auto-updater not work on older versions?

Because the official code signature was updated, which breaks the auto-updater for all previous versions. The README instructs you to manually download and install v2.0.2 or later to receive the update, and says future updates will be delivered automatically as expected.

### What do I need to run Every PDF from source?

Node.js v18 or higher, Python v3.10 or higher and Git. You clone the repository, run npm install, then npm run setup-backend to create the Python virtual environment and install the dependencies, and npm run dev to start the frontend and the backend together.

### What can Every PDF actually do to a PDF file?

Add text, signatures, images and checkboxes to a document, convert between PDF and other formats, split pages by range or by individual page numbers, merge files by drag and drop, add text or image watermarks, rotate and reorder pages, and add or remove password protection.

### Which frameworks is Every PDF built on?

Nextron, which combines Next.js and Electron, for the application shell, with React, TypeScript and Tailwind CSS in the frontend, a Python backend served with FastAPI, and Electron Builder for packaging.

## Sources

- [DDULDDUCK/every-pdf on GitHub](https://github.com/DDULDDUCK/every-pdf)
- [License: MIT](https://github.com/DDULDDUCK/every-pdf/blob/main/LICENSE)
- [Project website](https://github.com/DDULDDUCK/every-pdf/releases)
- [README](https://github.com/DDULDDUCK/every-pdf/blob/main/README.md)
- [Releases](https://github.com/DDULDDUCK/every-pdf/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/dduldduck-every-pdf
