A local-first desktop app for browsing and downloading books from OPDS libraries. Think Kindle Store / Apple Books for your federated catalogs — not a Calibre clone, not a reader, not a metadata editor. Just discovery, download, and (optionally) send-to-device.
Built with Tauri 2 + Rust on the backend and React + Tailwind 4 on the frontend.
- Browse multiple OPDS libraries as a unified, storefront-style home. Each source becomes its own section with horizontal rails fanned out from the catalog's navigation.
- OPDS 1 (Atom) and OPDS 2 (JSON) parsers, with HTTP Basic / Bearer / Cookie authentication.
- Federated search across every enabled library, with results de-duplicated by ISBN-13.
- Auto metadata enrichment from Open Library — fills in covers, descriptions, subjects, language, and publisher when the OPDS source doesn't supply them. Cached locally so the enrichment persists across sessions and decorates the library home too, not just the book detail.
- Downloads to
~/Books/Common Stacks/withTitle - Author.extnaming and collision handling. The Downloads view reads from disk directly, displays real EPUB covers/titles/authors extracted from each file, and offers a hover/right-click menu to reveal, rename, delete, or send a book. - Send-to-device targets as plugins:
- Crosspoint Reader — reverse-engineered HTTP upload over mDNS, with an optional EPUB image optimizer that recompresses inline images as JPEG before upload. Live per-image progress in the send modal.
- Send to Kindle (email) via SMTP.
- WebDAV (Nextcloud, ownCloud, KOReader, anything that speaks PUT).
- EPUB image optimizer transformer plugin (used by Crosspoint, available to any future send target).
- Local stale-while-revalidate cache so tabbing back into the Library is instant.
Common Stacks ships pre-configured with three OPDS sources:
| Source | Notes |
|---|---|
| Mayberry (https://mayberry.pub) | Public; no auth required. |
| Project Gutenberg (https://m.gutenberg.org/ebooks.opds/) | Public; no auth required. |
| Standard Ebooks (https://standardebooks.org/feeds/opds/all) | Shipped disabled. Enable in Settings → Libraries and add HTTP Basic auth (your Patrons Circle email as username, blank password). |
You can add your own from Settings → Add a library.
# one-time
bun install
# develop (auto-rebuilds Rust on change, HMRs the React side)
bun run tauri dev
# build a release bundle
bun run tauri buildPrereqs: Rust toolchain, Bun (or Node + npm), and the platform Tauri requirements (Xcode CLT on macOS, etc.).
| macOS | Linux | Windows | |
|---|---|---|---|
| Config + plugins | ~/Library/Application Support/Common Stacks/ |
~/.config/Common Stacks/ |
%APPDATA%\Common Stacks\ |
| Downloads (default) | ~/Books/Common Stacks/ |
~/Books/Common Stacks/ |
%USERPROFILE%\Books\Common Stacks\ |
Common Stacks is extensible by dropping a folder into the plugins directory. Plugins are regular executables or scripts (Python, Node, Go, Bash, anything with stdin/stdout) — no compile step, no FFI, no ABI fragility.
Three plugin categories:
- Metadata enricher — augments a book's metadata.
- Send-to target — delivers a downloaded file somewhere.
- Transformer — byte-level transform run before sending.
See docs/PLUGIN_DEVELOPMENT.md for the full
protocol, and examples/plugins/example-metadata/
for a complete Python plugin you can drop in to verify the loader.
common-stacks/
├── src/ ← React + Tailwind UI
│ ├── routes/ ← Library, Browse, Book, Downloads, Settings
│ ├── components/ ← CoverCard, DefaultCover, SendProgressModal, …
│ └── lib/ ← Typed Tauri command surface, caches
├── src-tauri/
│ ├── src/
│ │ ├── opds/ ← OPDS 1 + 2 parsers, OpenSearch resolver, auth
│ │ ├── dedup.rs ← ISBN-13 dedup, title/author fallback
│ │ ├── epub.rs ← EPUB metadata + cover extraction
│ │ ├── plugins/ ← Plugin SDK + built-ins + subprocess loader
│ │ │ ├── metadata/ ← Open Library enricher
│ │ │ ├── send/ ← Crosspoint, Kindle email, WebDAV
│ │ │ └── transform/ ← EPUB image optimizer
│ │ ├── commands.rs ← Tauri command handlers
│ │ └── state.rs ← Shared app state
│ └── tauri.conf.json
├── docs/
│ ├── PRD.md ← Product requirements / scope
│ └── PLUGIN_DEVELOPMENT.md
└── examples/plugins/
└── example-metadata/ ← Drop-in Python plugin demo
Some things Common Stacks intentionally isn't trying to be:
- An ebook reader (no in-app reading).
- A metadata management system (we enrich; we don't let you edit fields).
- A personal library organizer (no collections, no tagging).
- A Calibre clone or device driver framework.
- A DRM removal or conversion tool.
- A reading-progress tracker or note/highlight system.
Discovery → download → optional send. That's it.
See LICENSE.