# Realtime PDF
Desktop PDF watcher for macOS built with Tauri, Next.js, and React.
Realtime PDF watches a target PDF file, reloads it when the file changes on disk, keeps a persistent saved-history list, and can run per-PDF source hooks that regenerate the PDF when related files such as Laravel Blade templates change.
## Features
- Full-window PDF viewer powered by `@embedpdf/react-pdf-viewer`
- Persistent saved PDF history with disabled-but-removable missing entries
- Per-PDF hook lists
- Multiple hooks per PDF
- Hook template copy from another saved PDF
- Hook fields:
- watch path
- execute command
- execution path
- enabled toggle
- Debounced hook execution
- Persisted zoom level
- Persistent restore of the last watched PDF on reopen
## Install
### Homebrew
```bash
brew install --cask dickwu/tap/realtime-pdf
```
### If macOS says the app is damaged or cannot be opened
```bash
sudo xattr -d com.apple.quarantine /Applications/Realtime\ PDF.app/
```
## Usage
1. Open the app.
2. Click `Settings`.
3. Pick a PDF or paste a PDF path.
4. Reopen `Settings` to manage:
- saved PDF history
- hook definitions for the active PDF
- hook templates copied from another saved PDF
### Hook example
For a Laravel-generated PDF, one hook might be:
- Watch path: `~/Sites/app/resources/views/pdf/invoice.blade.php`
- Execution path: `~/Sites/app`
- Execute command: `php artisan test --filter=GenerateInvoicePdfTest`
If that command regenerates the watched PDF file, Realtime PDF reloads it automatically through the existing PDF watcher.
## In-app updates
Realtime PDF checks GitHub Releases for a new version on launch and every five minutes after that. The result lands in `Settings → App version`:
- **Up to date**: shows the current version and a `Check now` button.
- **Update available**: shows `Update to vX.Y.Z` and a primary button. Clicking it downloads the signed update bundle, replaces the installed `.app`, and relaunches.
Updates are signed with minisign at release time, so an update only installs if its signature matches the public key compiled into the running app.
The first install of any version still happens via DMG download or `brew install --cask dickwu/tap/realtime-pdf`. In-app auto-update only kicks in once an updater-enabled build is running.
If you installed via Homebrew and prefer to keep cask metadata in sync, you can also run `brew upgrade --cask realtime-pdf` instead of using the in-app updater — both paths work, but using one consistently avoids version drift between Homebrew's records and the installed binary.
## Development
### Prerequisites
- Bun
- Rust toolchain
- Tauri desktop build prerequisites for macOS
### Run
```bash
bun install
bun run dev
```
Run the desktop app with:
```bash
bunx tauri dev
```
### Verify
```bash
bun test
bunx tsc --noEmit
cargo check --manifest-path src-tauri/Cargo.toml
bunx tauri build --debug --no-bundle
```
## Project Structure
- `src/app/page.tsx` — main app UI
- `src/components/PdfViewer.tsx` — EmbedPDF wrapper
- `src/lib/pdf.ts` — shared viewer/history/hook types and helpers
- `src-tauri/src/lib.rs` — Tauri commands, PDF watcher, hook watcher runner
- `.github/workflows/` — CI and release automation
## License
MIT