[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-1438":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":15,"forks30d":15,"starsTrendScore":19,"compositeScore":20,"rankGlobal":9,"rankLanguage":9,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":9,"pushedAt":9,"updatedAt":43,"readmeContent":44,"aiSummary":45,"trendingCount":15,"starSnapshotCount":15,"syncStatus":46,"lastSyncTime":47,"discoverSource":48},1438,"bindery","vavallee\u002Fbindery","vavallee","Automated book download manager for Usenet. Monitor authors, search indexers, download via SABnzbd, and organize your library. The modern replacement for Readarr.",null,"Go",285,22,1,5,0,8,12,49,24,70.99,"MIT License",false,"main",true,[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"audiobooks","book-manager","calibre","docker","ebooks","go","helm","homelab","i18n","multilingual","opds","react","readarr-alternative","sabnzbd","self-hosted","sqlite","usenet","2026-06-12 04:00:09","\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Fvavallee\u002Fbindery\u002Fmain\u002F.github\u002Fassets\u002Flogo.png\" alt=\"Bindery\" width=\"120\" \u002F>\n\u003C\u002Fp>\n\n\u003Ch1 align=\"center\">Bindery\u003C\u002Fh1>\n\n\u003Cp align=\"center\">\n  \u003Cstrong>Automated book download manager for Usenet & Torrents\u003C\u002Fstrong>\u003Cbr>\n  Monitor authors. Search indexers. Download. Organize. Done.\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Factions\u002Fworkflows\u002Fci.yml\">\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg\" alt=\"CI\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fcodecov.io\u002Fgh\u002Fvavallee\u002Fbindery\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fcodecov\u002Fc\u002Fgithub\u002Fvavallee\u002Fbindery?logo=codecov&logoColor=white\" alt=\"codecov\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Freleases\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002Fvavallee\u002Fbindery\" alt=\"Release\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fpkgs\u002Fcontainer\u002Fbindery\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fghcr.io-vavallee%2Fbindery-blue\" alt=\"Docker\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgoreportcard.com\u002Freport\u002Fgithub.com\u002Fvavallee\u002Fbindery\">\u003Cimg src=\"https:\u002F\u002Fgoreportcard.com\u002Fbadge\u002Fgithub.com\u002Fvavallee\u002Fbindery\" alt=\"Go Report Card\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fblob\u002Fmain\u002FLICENSE\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Flicense\u002Fvavallee\u002Fbindery\" alt=\"License\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002FRpuYYRM9cZ\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-BINDERY-5865F2?logo=discord&logoColor=white\" alt=\"Discord\" \u002F>\u003C\u002Fa>\n\u003C\u002Fp>\n\n---\n\n\u003C!-- Hero: Books library — auto-switches between dark and light to match the viewer's OS theme -->\n\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs\u002Fscreenshots\u002Fbooks-desktop-dark.png\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"docs\u002Fscreenshots\u002Fbooks-desktop-light.png\">\n    \u003Cimg src=\"docs\u002Fscreenshots\u002Fbooks-desktop-dark.png\" alt=\"Bindery — Books library grid view\" width=\"1200\">\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs\u002Fscreenshots\u002Fauthors-desktop-dark.png\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"docs\u002Fscreenshots\u002Fauthors-desktop-light.png\">\n    \u003Cimg src=\"docs\u002Fscreenshots\u002Fauthors-desktop-dark.png\" alt=\"Bindery — Authors overview with monitoring badges\" width=\"1200\">\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs\u002Fscreenshots\u002Fauthor-detail-desktop-dark.png\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"docs\u002Fscreenshots\u002Fauthor-detail-desktop-light.png\">\n    \u003Cimg src=\"docs\u002Fscreenshots\u002Fauthor-detail-desktop-dark.png\" alt=\"Bindery — Author detail page with book list\" width=\"1200\">\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n\u003Ch4 align=\"center\">Mobile-friendly\u003C\u002Fh4>\n\n\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs\u002Fscreenshots\u002Fbooks-mobile-dark.png\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"docs\u002Fscreenshots\u002Fbooks-mobile-light.png\">\n    \u003Cimg src=\"docs\u002Fscreenshots\u002Fbooks-mobile-dark.png\" alt=\"Books — mobile\" width=\"280\">\n  \u003C\u002Fpicture>\n  &nbsp;&nbsp;&nbsp;\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs\u002Fscreenshots\u002Fauthors-mobile-dark.png\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"docs\u002Fscreenshots\u002Fauthors-mobile-light.png\">\n    \u003Cimg src=\"docs\u002Fscreenshots\u002Fauthors-mobile-dark.png\" alt=\"Authors — mobile\" width=\"280\">\n  \u003C\u002Fpicture>\n  &nbsp;&nbsp;&nbsp;\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs\u002Fscreenshots\u002Fauthor-detail-mobile-dark.png\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"docs\u002Fscreenshots\u002Fauthor-detail-mobile-light.png\">\n    \u003Cimg src=\"docs\u002Fscreenshots\u002Fauthor-detail-mobile-dark.png\" alt=\"Author detail — mobile\" width=\"280\">\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n---\n\n## Why Bindery?\n\n**Readarr is dead.** The official project was archived in June 2025 and its metadata backend (`api.bookinfo.club`) is permanently offline. Community forks rely on fragile Goodreads scrapers that break regularly. There was no reliable, open-source tool for automated book management on Usenet.\n\n**Bindery is the clean-room replacement.** Built from scratch in Go with a modern React UI, Bindery uses only stable, documented public APIs for book metadata. No scraping. No dead backends. No fragile dependencies.\n\n## Features\n\n### Library management\n- **Author monitoring** — Add authors and Bindery tracks all their works automatically via OpenLibrary's author works endpoint\n- **Book tracking** — Per-book monitor toggle, status workflow (wanted → downloading → downloaded → imported)\n- **Dual-format books** — Each book can hold an ebook *and* an audiobook simultaneously. The Book Detail page has separate format panels with independent status, file path, and grab buttons. The search pipeline uses Newznab category 7020 for ebooks and 3030 for audiobooks; the importer moves whole audiobook folders (multi-part `.m4b` \u002F `.mp3`) as one unit into a separate audiobook library root; the Wanted page lists each missing format as a separate row.\n- **Series support** — Books grouped by series with position tracking and dedicated Series page\n- **Edition tracking** — Multiple editions per work, with format, ISBN, publisher, page count\n- **Library scan** — Walk `\u002Fbooks\u002F` and reconcile existing files with wanted books in the database; trigger on-demand from **Settings → General → Scan Library**. Matching is four-tier: ASIN → title + author → series name + position number → fuzzy title. Files annotated with series info (e.g. `[Mistborn, Book 1]` or `(Dune Chronicles #2)`) are matched even when the title alone would be ambiguous.\n- **Author aliases** — Merge duplicate authors (\"RR Haywood\" \u002F \"R.R. Haywood\" \u002F \"R R Haywood\") into one canonical row from the Authors page; add-author flow detects aliases and prompts for merge instead of silently ingesting a duplicate\n\n### Search & downloads\n- **Newznab + Torznab** — Query multiple Usenet and torrent indexers in parallel, deduplicated and ranked\n- **SABnzbd, NZBGet, qBittorrent, Transmission, Deluge** — Full support for both Usenet and torrent download clients. All clients support **Use SSL** and **URL Base** for connections through a reverse-proxy subpath (configure under **Settings → Download Clients**).\n- **Auto-grab** — Scheduler searches for wanted books every 12h and automatically grabs the best result. Adding a new author or flipping a book to `wanted` fires an immediate search — no waiting for the next scheduled pass. Toggle the global kill-switch at **Settings → General → Auto-grab** to pause all automatic grabbing without losing your monitored list.\n- **Interactive search** — Manual per-book search from the Wanted page with full result details; Grab button shows a spinner while in-flight and a ✓ on success. Author Detail page has a **Search all wanted** button to queue bulk searches for all monitored wanted books for that author in one click.\n- **Smart matching** — Four-tier query fallback (`t=book` → `surname+title` → `author+title` → title); word-boundary keyword matching; contiguous-phrase requirement for multi-word titles; dual-author-anchor for ambiguous short titles; subtitle-aware (`Title: Subtitle`)\n- **Composite ranking** — Results scored by format quality, edition tags (RETAIL \u002F UNABRIDGED \u002F ABRIDGED), year match to the book's release year, grab count, size, and ISBN exact-match bonus\n- **Quality profiles** — Preference order for EPUB \u002F MOBI \u002F AZW3 \u002F PDF, with cutoff rules\n- **Language filter** — Preferred language setting (English by default); filters releases with foreign-language tags at word boundaries\n- **Custom formats** — Regex-based release scoring for freeleech, retail tags, etc.\n- **Delay profiles** — Wait N hours before grabbing to let higher-quality releases appear\n- **Blocklist** — Consulted on every search and auto-grab; prevents re-grabbing releases you've rejected. Add entries directly from History with one click\n- **Failure visibility** — Download errors surfaced in Queue (active) and History (permanent)\n\n### Import & organize\n- **Automatic import** — Completed downloads matched by NZO ID, placed in library with configurable naming template\n- **Import modes** — **Move** (default): source deleted after import. **Copy**: source kept so torrent clients continue seeding. **Hardlink**: zero extra disk, both paths share an inode (download dir and library must be on the same filesystem). Configurable under **Settings → General → Import Mode**.\n- **Naming tokens** — `{Author}`, `{SortAuthor}`, `{Title}`, `{Year}`, `{Series}`, `{SeriesNumber}`, `{ext}` with sanitized path components. `{Series}` expands to the book's primary series name (e.g. `Mistborn`); `{SeriesNumber}` to its position (e.g. `1` or `3.5`). Both silently expand to nothing for books not in a series, so the path collapses cleanly.\n- **Cross-filesystem moves** — Atomic rename when possible, copy+verify+delete for NFS\u002Fseparate volumes\n- **History** — Every grab, import, and failure recorded with full detail (shown inline on History page)\n- **Calibre library integration** — Three modes, all configurable under **Settings → Calibre**:\n  - **Off** — no Calibre interaction (default).\n  - **calibredb CLI** — every successful import calls `calibredb add --with-library \u003Cpath>`; the returned Calibre book id is persisted on the Bindery book row.\n  - **Plugin bridge** — POSTs the imported file path to the [Bindery Bridge plugin](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery-plugins) running an HTTP server inside a separate Calibre container; no shared binary or sidecar required. See [docs\u002FCALIBRE-PLUGIN.md](docs\u002FCALIBRE-PLUGIN.md) for setup.\n  - **Library import** — read an existing Calibre library's `metadata.db` directly and ingest it as Bindery's catalogue (idempotent; trigger from the Settings page or set `calibre.sync_on_startup`). Toggling the mode takes effect without a restart.\n\n### Metadata\n- **OpenLibrary** (primary) — Authors, books, editions, covers, ISBN lookup\n- **Google Books** (enricher) — Richer descriptions and ratings\n- **Hardcover.app** (enricher) — Community ratings and series data via GraphQL\n- **DNB** (enricher) — Deutsche Nationalbibliothek via the public SRU endpoint. No API key. Always on. Fills description, language, year, and publisher from MARC21 records — especially useful for German-language titles where OpenLibrary coverage is thin.\n- **Audnex** — Audiobook narrator, duration, cover, and description by Audible ASIN via the free [api.audnex.us](https:\u002F\u002Fapi.audnex.us) wrapper. Trigger with `POST \u002Fapi\u002Fv1\u002Fbook\u002F{id}\u002Fenrich-audiobook`.\n- **Audible catalogue** — Direct author lookup against Audible's public catalogue endpoint. Supplements OpenLibrary\u002FHardcover during `FetchAuthorBooks` when the author's effective media type is `audiobook` or `both`. Pulled books carry the ASIN and flow through the same `allowed_languages` filter as the OpenLibrary path — prolific authors (Sanderson, King, Rowling) gain the ASINs that OL\u002FHardcover are missing, without letting foreign-language editions slip past the default profile.\n- **Cover image proxy** — Cover images are fetched and cached server-side under `\u003CdataDir>\u002Fimage-cache\u002F` (30-day TTL). All `imageURL` fields in API responses are rewritten to `\u002Fapi\u002Fv1\u002Fimages?url=\u003Cencoded>` before leaving the server. The browser never contacts Goodreads, OpenLibrary, or Google Books directly — no IP leakage, no third-party tracking.\n- No Goodreads scraping. All sources use documented, stable public APIs.\n\n### Discover\n- **Recommendations engine** — The **Discover** page generates personalised book suggestions from multiple signals: next books in series you're reading, new releases from monitored authors, genre-similar titles (requires ≥ 20 books in library), OpenLibrary subject-based popular picks, and Hardcover.app wishlist cross-reference.\n- **Taste profile** — Built from your downloaded\u002Fimported books: preferred genres, era, language, authors, and series. Recency scoring is relative to the median publication year of your library rather than the current year, so backlist readers aren't penalised.\n- **Discover filters** — Candidates are hard-filtered: already-owned, dismissed, excluded-author, wrong-language, fewer-than-50-ratings, sub-3.0-rated, and collection\u002Fomnibus titles are all suppressed. Only individual, reasonably-rated books reach the page.\n- **Dismiss \u002F exclude** — Mark a recommendation as \"not interested\" or exclude an author entirely from future suggestions. Dismissals persist across engine runs.\n\n### Migration\n- **CSV import** — Upload a newline-separated list of author names (or a `name,monitored,searchOnAdd` CSV); each name is resolved against OpenLibrary.\n- **Readarr import** — Upload `readarr.db` directly. Authors are re-resolved via OpenLibrary (Goodreads IDs aren't portable since `bookinfo.club` is dead); Indexers, download clients, and blocklist entries port structurally. Run a library scan afterward to match existing files.\n- **CLI** — `bindery migrate csv \u003Cpath>` and `bindery migrate readarr \u003Cpath>` for first-time bulk imports without opening the UI.\n- **UI** — Settings → Import tab with file upload + per-section result summary.\n\n### Operations\n- **Webhook notifications** — Configurable HTTP callbacks for grab \u002F import \u002F failure events (pipe to Apprise, ntfy, Home Assistant, etc.)\n- **Metadata profiles** — Filter books by language, popularity, page count, ISBN presence\n- **Import lists** — Auto-add authors\u002Fbooks from external sources; exclusion list to skip unwanted entries\n- **Tag system** — Scope indexers\u002Fprofiles\u002Fnotifications to specific authors\n- **Backup\u002Frestore** — Snapshot the SQLite database on demand\n- **Log viewer** — Settings → Logs persists entries to the database and survives restarts. Filterable by date range, level, component, and full-text search. Retention period defaults to 14 days and is configurable. Runtime log level switchable to DEBUG without restarting via `PUT \u002Fapi\u002Fv1\u002Fsystem\u002Floglevel`\n- **Authentication** — First-run setup creates an admin account (argon2id password hashing, signed session cookies). Four modes: **Enabled** (always require login), **Local only** (bypass auth for private IPs — home network convenience), **Disabled** (no auth, trusted network only), **Proxy** (trust an upstream `X-Forwarded-User` header from a configured trusted proxy — drop-in for Authelia \u002F Authentik \u002F oauth2-proxy forward-auth). Per-account API key for external integrations. Per-IP rate limiting on the login endpoint (thresholds configurable via `BINDERY_RATE_LIMIT_MAX_FAILURES` \u002F `BINDERY_RATE_LIMIT_WINDOW_MINUTES`). CSRF double-submit tokens harden browser mutations (API-key clients exempt).\n- **Arr-compatible queue API** — `GET \u002Fapi\u002Fqueue` exposes a Sonarr\u002FRadarr-style queue payload for external tools such as [Harpoon](https:\u002F\u002Fgithub.com\u002Fharpoon-io\u002Fharpoon). Returns `totalRecords`, per-record live size\u002Fsizeleft, status, client name, remote ID, and protocol. Supports pagination and sort. API-key authentication required; browser-session CSRF protections do not apply to this endpoint.\n- **OIDC single sign-on** — Native Authorization Code + PKCE client with multi-provider support. Pre-configured for Google, GitHub (via Dex), Authelia, and Keycloak; any compliant IdP works. Users identified by stable `(issuer, sub)` — safe against email\u002Fusername changes. Managed under Settings → Authentication.\n- **Multi-user mode** — Per-user libraries, monitored authors, profiles, and downloads. Admin role manages indexers, download clients, and users; standard users see only their own catalogue. Users can be created locally, auto-provisioned via OIDC, or forward-auth mapped by username. Admin password reset from the Users page.\n\n### UI\n- **Multilingual UI** — English, French, German, Dutch, Spanish, Filipino (Tagalog), and Indonesian. Language auto-detected from the browser; manual override in Settings → General → Language. Persists to `localStorage` so the first paint is always in the right language.\n- **Light and dark themes** — iOS-style slider toggle in Settings → General → Appearance. First-load default respects the browser's `prefers-color-scheme`; preference persists to localStorage.\n- **Modern React SPA** — React 19 + TypeScript + Tailwind CSS 3, built with Vite.\n- **Detail pages** — Routed `\u002Fbook\u002F:id` and `\u002Fauthor\u002F:id` pages replace the previous modal flow. Deep-linkable, back-button friendly, hold per-book history inline.\n- **Grid \u002F Table view toggle** — Switch between poster-grid and dense-table views on the Books and Authors pages; choice persists per page.\n- **Mobile-friendly** — Responsive layout with hamburger nav, card views for History\u002FBlocklist, agenda view for Calendar. Table views hide less-critical columns on narrow viewports.\n- **Pagination everywhere** — First\u002FPrev\u002FNext\u002FLast + page numbers + configurable page size on all list pages; page size persists per-page in `localStorage`\n- **Search, filter, sort** — On Authors, Books, Wanted, and History pages. Authors can be filtered by `Monitored \u002F Unmonitored`. Author detail page sorts books by publication date and filters by type, status, or released\u002Fupcoming. Books filter chips include `Type: Ebook \u002F Audiobook`; Books view shows the author inline.\n- **Calendar view** — Upcoming book releases from monitored authors, with compact dot-indicator grid on mobile\n- **Full REST API** — Every feature accessible via HTTP for scripting and integration\n- **OPDS 1.2 catalogue at `\u002Fopds\u002Fv1.2\u002F`** — browse and download your library from KOReader, Moon+ Reader, or any OPDS-capable reading app without Calibre. Authenticated with HTTP Basic Auth (any username, API key as password). Feeds: catalog root, recent, by author, search.\n\n### Packaging\n- **Single binary** — Frontend embedded via `go:embed`. No nginx, no sidecars, no complexity\n- **Distroless Docker image** — Minimal attack surface, published to GHCR\n- **Kubernetes-ready** — Helm chart included for ArgoCD \u002F Flux deployments\n- **SQLite + WAL** — Pure Go driver (`modernc.org\u002Fsqlite`), no CGO, no external database to manage\n\n## Quick Start\n\n### Docker\n\n```bash\ndocker run -d \\\n  --name bindery \\\n  -p 8787:8787 \\\n  -v \u002Fpath\u002Fto\u002Fconfig:\u002Fconfig \\\n  -v \u002Fpath\u002Fto\u002Fbooks:\u002Fbooks \\\n  -v \u002Fpath\u002Fto\u002Fdownloads:\u002Fdownloads \\\n  ghcr.io\u002Fvavallee\u002Fbindery:latest\n```\n\nOpen \u003Chttp:\u002F\u002Flocalhost:8787>, follow the first-run setup to create the admin account, and you're in.\n\n### Binary (Linux \u002F macOS \u002F Windows)\n\nDownload the archive for your platform from the [latest release](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Freleases\u002Flatest), extract, and run:\n\n```bash\n# Linux \u002F macOS\ntar -xzf bindery_\u003Cversion>_\u003Cos>_\u003Carch>.tar.gz\n.\u002Fbindery\n```\n\n```cmd\n:: Windows\n:: Unzip bindery_\u003Cversion>_windows_amd64.zip, then:\nbindery.exe\n```\n\nOn first run the database lands in the platform's standard location:\n\n| Platform | Default `BINDERY_DB_PATH` | Default `BINDERY_DATA_DIR` |\n|----------|---------------------------|----------------------------|\n| Linux \u002F Docker \u002F Helm | `\u002Fconfig\u002Fbindery.db` | `\u002Fconfig` |\n| Windows | `%APPDATA%\\Bindery\\bindery.db` | `%APPDATA%\\Bindery` |\n| macOS | `~\u002FLibrary\u002FApplication Support\u002FBindery\u002Fbindery.db` | `~\u002FLibrary\u002FApplication Support\u002FBindery` |\n\nSet `BINDERY_DB_PATH` \u002F `BINDERY_DATA_DIR` if you want them elsewhere. The resolved paths are logged at startup (`\"starting bindery\"` log line).\n\nFor Docker Compose, Kubernetes (Helm), running as a specific UID\u002FGID, and upgrade notes, see **[docs\u002FDEPLOYMENT.md](docs\u002FDEPLOYMENT.md)**.\n\n## Configuration\n\nBindery is configured through the web UI under **Settings**. Core env vars:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BINDERY_PORT` | `8787` | HTTP server port |\n| `BINDERY_DB_PATH` | platform-dependent (see [Binary install](#binary-linux--macos--windows)) | SQLite database path |\n| `BINDERY_DATA_DIR` | platform-dependent (see [Binary install](#binary-linux--macos--windows)) | Config directory (backups live here) |\n| `BINDERY_LOG_LEVEL` | `info` | `debug` \u002F `info` \u002F `warn` \u002F `error` |\n| `BINDERY_DOWNLOAD_DIR` | `\u002Fdownloads` | Where the download client places completed downloads |\n| `BINDERY_LIBRARY_DIR` | `\u002Fbooks` | Destination for imported ebook files |\n| `BINDERY_AUDIOBOOK_DIR` | falls back to `BINDERY_LIBRARY_DIR` | Destination for imported audiobook folders |\n| `BINDERY_ENHANCED_HARDCOVER_API` | `false` | Enables Hardcover-token-backed series search, linking, catalog diffs, and missing-book fill when also enabled in Settings |\n\nThe full variable reference (path remapping, API key seeding, `BINDERY_PUID` \u002F `BINDERY_PGID` sanity checks) is in **[docs\u002FDEPLOYMENT.md](docs\u002FDEPLOYMENT.md#environment-variables)**.\n\n## Metadata Sources\n\nBindery aggregates book metadata from multiple open sources:\n\n| Source | Auth Required | Used For |\n|--------|---------------|----------|\n| [OpenLibrary](https:\u002F\u002Fopenlibrary.org) | None | Primary: authors, books, editions, covers, ISBN lookup |\n| [Google Books](https:\u002F\u002Fdevelopers.google.com\u002Fbooks) | API key (free) | Enrichment: descriptions, ratings |\n| [Hardcover.app](https:\u002F\u002Fhardcover.app) | None (public GraphQL) | Enrichment: community ratings, series |\n| [DNB](https:\u002F\u002Fwww.dnb.de\u002FEN\u002FProfessionell\u002FMetadatendienste\u002FDatenbezug\u002FSRU\u002Fsru_node.html) | None (public SRU) | Enrichment: descriptions, language, year for German-language titles |\n| [Audnex](https:\u002F\u002Fapi.audnex.us) | None | Audiobook narrator, duration, cover, description by ASIN |\n| [Audible](https:\u002F\u002Faudible.com) | None | Supplemental audiobook author lookup — pulls ASINs OpenLibrary\u002FHardcover miss |\n\nNo Goodreads scraping. All sources use documented, stable public APIs. Cover images are fetched and cached server-side (`GET \u002Fapi\u002Fv1\u002Fimages`) — the browser never contacts external image hosts directly.\n\n## Supported Integrations\n\n### Download clients\n- **SABnzbd** — full support (NZB submission, queue\u002Fhistory polling, pause\u002Fresume\u002Fdelete)\n- **NZBGet** — JSON-RPC v2 (NZB submission, queue\u002Fhistory polling, remove)\n- **qBittorrent** — WebUI API v2 with Username\u002FPassword auth (add magnet\u002FURL, list\u002Fdelete torrents)\n- **Transmission** — RPC API with Username\u002FPassword auth (add magnet\u002FURL, list\u002Fdelete torrents)\n- **Deluge** — JSON-RPC with cookie auth (add magnet\u002FURL, list\u002Fdelete torrents)\n\nAll clients support **Use SSL** (HTTPS) and **URL Base** (reverse-proxy subpath). Configure both under **Settings → Download Clients**.\n\n### Indexers\n- **Newznab** (Usenet) — NZBGeek, NZBFinder, NZBPlanet, DrunkenSlug, etc.\n- **Torznab** (Torrents) — Prowlarr, Jackett, or direct Torznab endpoints\n- **Configurable categories per indexer** — set custom Newznab category IDs in Settings → Indexers (e.g. `7120` for German books, `3130` for German audio on SceneNZBs). Bindery routes 7xxx IDs to ebook searches and 3xxx IDs to audiobook searches automatically.\n\n### Notifications\n- **Generic webhooks** — Any HTTP endpoint. Pipe to Apprise, ntfy, Home Assistant, Slack, Discord via proxies.\n\n## Architecture\n\nBindery is a single Go binary with the React frontend embedded via `go:embed`:\n\n```\n   Newznab \u002F Torznab\n      indexers\n         │\n         ▼\n┌────────────────────────────┐\n│         Bindery            │──► SABnzbd \u002F NZBGet \u002F qBittorrent \u002F Transmission \u002F Deluge\n│  Go backend + React SPA    │──► \u002Fbooks\u002F library\n│  SQLite (WAL mode)         │──► Webhook notifications\n└────────────────────────────┘\n    ▲                    ▲\n    │                    │\nOpenLibrary      Google Books, Hardcover.app, DNB\n (primary)                 (enrichers)\n```\n\n- **Backend:** Go 1.25 with [chi](https:\u002F\u002Fgithub.com\u002Fgo-chi\u002Fchi) router\n- **Database:** SQLite via [modernc.org\u002Fsqlite](https:\u002F\u002Fpkg.go.dev\u002Fmodernc.org\u002Fsqlite) (pure Go, no CGO)\n- **Frontend:** React 19 + TypeScript + Tailwind CSS + [Vite](https:\u002F\u002Fvite.dev)\n- **Container:** Multi-stage build on [distroless](https:\u002F\u002Fgithub.com\u002FGoogleContainerTools\u002Fdistroless) (minimal attack surface)\n\n## API\n\nBindery exposes a full REST API under `\u002Fapi\u002Fv1`. A few highlights:\n\n```\nGET    \u002Fapi\u002Fv1\u002Fhealth                    - server health\nGET    \u002Fapi\u002Fv1\u002Fauthor                    - list authors\nPOST   \u002Fapi\u002Fv1\u002Fauthor                    - add author (triggers async book fetch)\nGET    \u002Fapi\u002Fv1\u002Fbook?status=wanted        - filter books by status\nPOST   \u002Fapi\u002Fv1\u002Fbook\u002F{id}\u002Fsearch          - manual indexer search for a book\nGET    \u002Fapi\u002Fv1\u002Fqueue                     - active downloads with live downloader overlay\nPOST   \u002Fapi\u002Fv1\u002Fqueue\u002Fgrab                - submit a search result to download client\nGET    \u002Fapi\u002Fqueue                        - *arr-compatible queue for external tools\nGET    \u002Fapi\u002Fv1\u002Fhistory                   - grab\u002Fimport\u002Ffailure events\nPOST   \u002Fapi\u002Fv1\u002Fhistory\u002F{id}\u002Fblocklist    - add a history event's release to the blocklist\nGET    \u002Fapi\u002Fv1\u002Fblocklist                 - blocked releases\nGET    \u002Fapi\u002Fv1\u002Fimages?url=\u003Cencoded>      - proxied + cached cover image (30-day TTL)\nPOST   \u002Fapi\u002Fv1\u002Fnotification\u002F{id}\u002Ftest    - fire a test webhook\nPOST   \u002Fapi\u002Fv1\u002Fbackup                    - snapshot the database\n```\n\n### Authentication\n\nEvery request to `\u002Fapi\u002Fv1\u002F*` (except `\u002Fhealth`, `\u002Fauth\u002Fstatus`, `\u002Fauth\u002Flogin`, `\u002Fauth\u002Flogout`, `\u002Fauth\u002Fsetup`) is authenticated. A request is allowed if **any** of:\n\n- Auth mode is **Disabled**.\n- Auth mode is **Local only** and the request originates from a private-range IP (`10\u002F8`, `172.16\u002F12`, `192.168\u002F16`, `127\u002F8`, IPv6 ULA, link-local, loopback).\n- A valid `X-Api-Key` header (or `?apikey=` query param) matches the stored key.\n- A valid `bindery_session` cookie is present.\n\nOtherwise the server responds with `401`. The API key lives in **Settings → General → Security** — copy it from there for scripts and integrations. Regenerating the key invalidates any existing consumers.\n\n## Documentation\n\n| Topic | Where |\n|-------|-------|\n| **Quickstart** — first author to first grab in 10 minutes | [Wiki](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fwiki\u002FQuickstart) |\n| **Deployment** — Docker, Compose, k8s\u002FHelm, binary, UID\u002FGID, upgrades | [docs\u002FDEPLOYMENT.md](docs\u002FDEPLOYMENT.md) |\n| **ABS import** — setup, path remap, review queue, rollback, and matching behavior | [docs\u002Fabs_import.md](docs\u002Fabs_import.md) |\n| **Enhanced Hardcover series** — token setup, series linking, catalog diffs, and missing-book fill | [docs\u002FHardcover-Series-Wiki.md](docs\u002FHardcover-Series-Wiki.md) |\n| **Calibre plugin bridge** — cross-container Calibre integration via the Bindery Bridge plugin | [docs\u002FCALIBRE-PLUGIN.md](docs\u002FCALIBRE-PLUGIN.md) |\n| **Roadmap** — planned work, scope notes, and explicitly-out-of-scope items (Z-Library, OpenBooks, etc.) | [docs\u002FROADMAP.md](docs\u002FROADMAP.md) |\n| **Contributing & CI checks** — dev setup, full quality\u002Fsecurity matrix, local check suite | [CONTRIBUTING.md](CONTRIBUTING.md) |\n| **Changelog** — release notes | [CHANGELOG.md](CHANGELOG.md) |\n| **Reverse-proxy & SSO setups** — Traefik \u002F Caddy \u002F Nginx \u002F Authelia \u002F Authentik recipes | [Wiki](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fwiki\u002FReverse-proxy-and-SSO) |\n| **Troubleshooting** — permission-denied, path-remap, import failures | [Wiki](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fwiki\u002FTroubleshooting) |\n| **Indexer & download-client recipes** — NZBGeek \u002F DrunkenSlug \u002F Prowlarr \u002F Jackett \u002F SAB \u002F qBit tips | [Wiki](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fwiki\u002FIndexer-and-downloader-recipes) |\n| **Migrating from Readarr** — step-by-step with known failure modes | [Wiki](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fwiki\u002FMigrating-from-Readarr) |\n\n## Community\n\n- **Discord** — real-time help, setup questions, release chat: [discord.gg\u002FRpuYYRM9cZ](https:\u002F\u002Fdiscord.gg\u002FRpuYYRM9cZ). The `#support` channel is the best place to ask; `#changelog` is updated on every release.\n- **GitHub Issues** — bug reports and feature requests: [issues](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fissues).\n- **GitHub Discussions** — open-ended design questions, show-and-tell, integration recipes: [discussions](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fdiscussions).\n\nPlease keep security reports out of Discord and public issues — see [SECURITY.md](SECURITY.md) for the private disclosure channel.\n\n## Security\n\nBindery holds API keys, reaches LAN services, and writes to disk. We take that\nseriously.\n\n\u003Cp>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fsecurity\u002Fcode-scanning\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Factions\u002Fworkflow\u002Fstatus\u002Fvavallee\u002Fbindery\u002Fsecurity.yml?branch=main&label=security%20scans&logo=github\" alt=\"Security scans\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fsecurityscorecards.dev\u002Fviewer\u002F?uri=github.com\u002Fvavallee\u002Fbindery\">\u003Cimg src=\"https:\u002F\u002Fapi.securityscorecards.dev\u002Fprojects\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fbadge\" alt=\"OpenSSF Scorecard\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fsecurity\u002Fdependabot\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDependabot-enabled-brightgreen?logo=dependabot\" alt=\"Dependabot\" \u002F>\u003C\u002Fa>\n  \u003Ca href=\"SECURITY.md\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fsecurity-policy-blue\" alt=\"Security policy\" \u002F>\u003C\u002Fa>\n\u003C\u002Fp>\n\nEvery push and every weekly cron runs gosec, govulncheck, Semgrep, gitleaks,\nTrivy, Grype, Dockle, Syft, ZAP baseline, and OpenSSF Scorecard. Findings\nupload to GitHub's Security tab as SARIF and are public-readable. Release\nimages ship with SLSA build provenance and Syft SBOMs.\n\nHighlights of the in-app controls:\n\n- **SSRF guards** on every outbound URL (webhooks, indexers, download clients), with DNS-rebinding defense.\n- **Hardened headers** — CSP, `X-Frame-Options: DENY`, `Referrer-Policy`, auto HSTS when TLS is present.\n- **Cookie `Secure` auto-detect** via TLS or `X-Forwarded-Proto`, overridable.\n- **Distroless, non-root, read-only rootfs** container with all caps dropped and RuntimeDefault seccomp.\n- **Digest-pinned base images** tracked by Dependabot.\n\nTo report a vulnerability, follow the process in **[SECURITY.md](SECURITY.md)**.\nThe full threat model, control catalogue, and verification recipes live on\nthe [wiki Security page](https:\u002F\u002Fgithub.com\u002Fvavallee\u002Fbindery\u002Fwiki\u002FSecurity).\n\n## Telemetry\n\nBindery sends one anonymous ping per day to [api.getbindery.dev](https:\u002F\u002Fapi.getbindery.dev) so the maintainer can count active installs. The ping contains:\n\n| Field | Value |\n|---|---|\n| `install_id` | Random UUID generated on first run, stored locally |\n| `version` | Running binary version (e.g. `v1.4.1`) |\n| `os` | `linux`, `darwin`, `windows` |\n| `arch` | `amd64`, `arm64` |\n\nNo hostnames, IP addresses, library contents, or personal data are included. The server returns the latest published version, which Bindery uses for update notifications.\n\n**To opt out:** set `telemetry.enabled` to `false` in **Settings → General**, or set the env var `BINDERY_TELEMETRY_DISABLED=true` before first run.\n\n## Contributing\n\nPRs, issues, and feedback welcome. See **[CONTRIBUTING.md](CONTRIBUTING.md)** for the dev setup, the full local check suite, and the PR flow. Tracked feature work lives in **[docs\u002FROADMAP.md](docs\u002FROADMAP.md)** — open an issue before starting anything substantial.\n\n## License\n\nMIT. See [LICENSE](LICENSE) for details.\n\n## Acknowledgments\n\n- The [*arr community](https:\u002F\u002Fwiki.servarr.com\u002F) for pioneering the monitor-search-download-import pattern\n- [OpenLibrary](https:\u002F\u002Fopenlibrary.org) for free, open book metadata\n- The Readarr project for the original vision, even though the implementation couldn't be sustained\n","Bindery 是一个自动化书籍下载管理器，支持Usenet和Torrents。其核心功能包括监控作者、搜索索引器、通过SABnzbd下载以及组织你的电子书库，是Readarr的现代替代品。项目使用Go语言开发，具备良好的国际化支持和响应式设计，适用于桌面和移动设备。它适合需要自动管理和扩展个人电子书收藏的用户，特别是那些希望通过Usenet或Torrents获取资源并希望将这些资源整合到统一管理平台中的用户。此外，Bindery还提供了Docker镜像，方便用户在自托管环境中部署。",2,"2026-06-11 02:43:46","CREATED_QUERY"]