{"id":48738677,"url":"https://github.com/vavallee/bindery","last_synced_at":"2026-05-15T03:12:35.527Z","repository":{"id":350756386,"uuid":"1208135933","full_name":"vavallee/bindery","owner":"vavallee","description":"Automated book download manager for Usenet. Monitor authors, search indexers, download via SABnzbd, and organize your library. The modern replacement for Readarr.","archived":false,"fork":false,"pushed_at":"2026-05-11T19:03:48.000Z","size":10482,"stargazers_count":243,"open_issues_count":27,"forks_count":14,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-05-11T19:30:58.979Z","etag":null,"topics":["audiobooks","book-manager","calibre","docker","ebooks","go","helm","homelab","i18n","multilingual","opds","react","readarr-alternative","sabnzbd","self-hosted","sqlite","usenet"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vavallee.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-11T21:40:44.000Z","updated_at":"2026-05-11T18:47:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"2d84f241-23a8-4216-a2f9-6dfcf0b28879","html_url":"https://github.com/vavallee/bindery","commit_stats":null,"previous_names":["vavallee/bindery"],"tags_count":87,"template":false,"template_full_name":null,"purl":"pkg:github/vavallee/bindery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vavallee%2Fbindery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vavallee%2Fbindery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vavallee%2Fbindery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vavallee%2Fbindery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vavallee","download_url":"https://codeload.github.com/vavallee/bindery/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vavallee%2Fbindery/sbom","scorecard":{"id":1246199,"data":{"date":"2026-04-18T04:20:57Z","repo":{"name":"github.com/vavallee/bindery","commit":"abfe756f508a5dfb4b4272796131c2be79474b94"},"scorecard":{"version":"v5.0.0","commit":"ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4"},"score":6.4,"checks":[{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#binary-artifacts"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#branch-protection"}},{"name":"CI-Tests","score":9,"reason":"16 out of 17 merged PRs checked by a CI test -- score normalized to 9","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#ci-tests"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#cii-best-practices"}},{"name":"Code-Review","score":0,"reason":"Found 0/26 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#code-review"}},{"name":"Contributors","score":0,"reason":"project has 0 contributing companies or organizations -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#contributors"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#dangerous-workflow"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#dependency-update-tool"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#license"}},{"name":"Maintained","score":0,"reason":"project was created in last 90 days. please review its contents carefully","details":["Warn: Repository was created in last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#maintained"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/ci.yml:15"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":8,"reason":"dependency not pinned by hash detected -- score normalized to 8","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/scorecard.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/vavallee/bindery/scorecard.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/scorecard.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/vavallee/bindery/scorecard.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/scorecard.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/vavallee/bindery/scorecard.yml/main?enable=pin","Warn: goCommand not pinned by hash: .github/workflows/ci.yml:215","Warn: goCommand not pinned by hash: .github/workflows/security.yml:56","Warn: npmCommand not pinned by hash: .github/workflows/security.yml:88","Warn: pipCommand not pinned by hash: .github/workflows/security.yml:117","Info:  36 out of  38 GitHub-owned GitHubAction dependencies pinned","Info:  19 out of  20 third-party GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned","Info:   3 out of   3 containerImage dependencies pinned","Info:   6 out of   7 npmCommand dependencies pinned","Info:   0 out of   2 goCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#pinned-dependencies"}},{"name":"SAST","score":9,"reason":"SAST tool is not run on all commits -- score normalized to 9","details":["Warn: 20 commits out of 21 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#sast"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#security-policy"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v0.18.1 not signed: https://api.github.com/repos/vavallee/bindery/releases/310599140","Warn: release artifact v0.18.0 not signed: https://api.github.com/repos/vavallee/bindery/releases/310593215","Warn: release artifact v0.17.0 not signed: https://api.github.com/repos/vavallee/bindery/releases/310193726","Warn: release artifact v0.16.0 not signed: https://api.github.com/repos/vavallee/bindery/releases/310149790","Warn: release artifact v0.15.2 not signed: https://api.github.com/repos/vavallee/bindery/releases/310035847","Warn: release artifact v0.18.1 does not have provenance: https://api.github.com/repos/vavallee/bindery/releases/310599140","Warn: release artifact v0.18.0 does not have provenance: https://api.github.com/repos/vavallee/bindery/releases/310593215","Warn: release artifact v0.17.0 does not have provenance: https://api.github.com/repos/vavallee/bindery/releases/310193726","Warn: release artifact v0.16.0 does not have provenance: https://api.github.com/repos/vavallee/bindery/releases/310149790","Warn: release artifact v0.15.2 does not have provenance: https://api.github.com/repos/vavallee/bindery/releases/310035847"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#signed-releases"}},{"name":"Token-Permissions","score":9,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/security.yml:217","Info: topLevel 'contents' permission set to 'read': .github/workflows/ci.yml:10","Info: topLevel 'contents' permission set to 'read': .github/workflows/scorecard.yml:19","Info: topLevel 'actions' permission set to 'read': .github/workflows/scorecard.yml:18","Info: topLevel 'contents' permission set to 'read': .github/workflows/security.yml:12","Warn: topLevel 'security-events' permission set to 'write': .github/workflows/security.yml:13","Info: topLevel 'actions' permission set to 'read': .github/workflows/security.yml:14","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#token-permissions"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ea7e27ed41b76ab879c862fa0ca4cc9c61764ee4/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2026-04-18T06:31:32.083Z","repository_id":350756386,"created_at":"2026-04-18T06:31:32.083Z","updated_at":"2026-04-18T06:31:32.083Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33051914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-15T02:00:06.351Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audiobooks","book-manager","calibre","docker","ebooks","go","helm","homelab","i18n","multilingual","opds","react","readarr-alternative","sabnzbd","self-hosted","sqlite","usenet"],"created_at":"2026-04-12T06:01:08.426Z","updated_at":"2026-05-15T03:12:35.513Z","avatar_url":"https://github.com/vavallee.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/vavallee/bindery/main/.github/assets/logo.png\" alt=\"Bindery\" width=\"120\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eBindery\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eAutomated book download manager for Usenet \u0026 Torrents\u003c/strong\u003e\u003cbr\u003e\n  Monitor authors. Search indexers. Download. Organize. Done.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/vavallee/bindery/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/vavallee/bindery/actions/workflows/ci.yml/badge.svg\" alt=\"CI\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/vavallee/bindery\"\u003e\u003cimg src=\"https://img.shields.io/codecov/c/github/vavallee/bindery?logo=codecov\u0026logoColor=white\" alt=\"codecov\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vavallee/bindery/releases\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/vavallee/bindery\" alt=\"Release\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vavallee/bindery/pkgs/container/bindery\"\u003e\u003cimg src=\"https://img.shields.io/badge/ghcr.io-vavallee%2Fbindery-blue\" alt=\"Docker\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://goreportcard.com/report/github.com/vavallee/bindery\"\u003e\u003cimg src=\"https://goreportcard.com/badge/github.com/vavallee/bindery\" alt=\"Go Report Card\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vavallee/bindery/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/vavallee/bindery\" alt=\"License\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://discord.gg/RpuYYRM9cZ\"\u003e\u003cimg src=\"https://img.shields.io/badge/Discord-BINDERY-5865F2?logo=discord\u0026logoColor=white\" alt=\"Discord\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/author-detail-desktop-dark.png\" alt=\"Bindery — Author detail page with monitored books\" width=\"1200\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/authors-desktop-dark.png\" alt=\"Bindery — Authors overview with monitoring badges\" width=\"1200\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/books-desktop-dark.png\" alt=\"Bindery — Books library grid view\" width=\"1200\"\u003e\n\u003c/p\u003e\n\n\u003ch4 align=\"center\"\u003eMobile-friendly\u003c/h4\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/screenshots/books-mobile-dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/screenshots/books-mobile-light.png\"\u003e\n    \u003cimg src=\"docs/screenshots/books-mobile-dark.png\" alt=\"Books — mobile\" width=\"280\"\u003e\n  \u003c/picture\u003e\n  \u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/screenshots/authors-mobile-dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/screenshots/authors-mobile-light.png\"\u003e\n    \u003cimg src=\"docs/screenshots/authors-mobile-dark.png\" alt=\"Authors — mobile\" width=\"280\"\u003e\n  \u003c/picture\u003e\n  \u0026nbsp;\u0026nbsp;\u0026nbsp;\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/screenshots/author-detail-mobile-dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/screenshots/author-detail-mobile-light.png\"\u003e\n    \u003cimg src=\"docs/screenshots/author-detail-mobile-dark.png\" alt=\"Author detail — mobile\" width=\"280\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\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 via OpenLibrary's author-works endpoint, with per-book monitor toggles and a `wanted → downloading → downloaded → imported` workflow.\n- Dual-format books — each title holds an ebook *and* an audiobook in independent slots, with separate search, grab, and import pipelines, and the audiobook side moves multi-part `.m4b` / `.mp3` folders as one unit.\n- Series support with position tracking, edition tracking (format / ISBN / publisher / page count), Calendar view of upcoming releases, and multiple library roots.\n- Library scan with four-tier matching: ASIN → title + author → series name + position → fuzzy title. Honours librarian sort-suffix form (`Title, The`) and series-annotated filenames (`[Mistborn, Book 1]`).\n- Author aliases (`RR Haywood` / `R.R. Haywood` / `R R Haywood` merge into one canonical row), and metadata re-bind to correct a wrong match without delete-and-re-add.\n\n**Search \u0026 downloads**\n- Newznab + Torznab indexers queried in parallel, deduplicated, then composite-ranked by format quality, edition tags (RETAIL / UNABRIDGED / ABRIDGED), year match, grab count, size, and ISBN exact-match bonus.\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- SABnzbd, NZBGet, qBittorrent, Transmission, Deluge — with **Use SSL** and **URL Base** for reverse-proxy subpaths.\n- Auto-grab sweep every 12h, immediate search on add or `wanted` flip, plus interactive per-book search and \"Search all wanted\" per author. Global kill-switch pauses auto-grab without losing your monitored list.\n- Quality profiles (EPUB / MOBI / AZW3 / PDF), language filter, regex-based custom formats, delay profiles, blocklist (consulted on every search; one-click add from History), and failure visibility in Queue and History.\n\n**Import \u0026 organize**\n- Completed downloads matched by NZO ID and placed in the library with configurable naming. Modes: **Move** (default), **Copy** (keep source for seeding), **Hardlink** (zero extra disk; same filesystem required).\n- Naming tokens — `{Author}`, `{SortAuthor}`, `{Title}`, `{Year}`, `{Series}`, `{SeriesNumber}`, `{ext}` — collapse cleanly for non-series books.\n- Cross-filesystem-safe moves: atomic rename when possible, copy + verify + delete for NFS / separate volumes. Full grab / import / failure history per book.\n- Calibre integration in three modes: `calibredb` CLI hook on import, [Bindery Bridge plugin](https://github.com/vavallee/bindery-plugins) (cross-container), or direct read of an existing Calibre library's `metadata.db` as Bindery's catalogue.\n\n**Metadata sources** — all stable, documented, public APIs. No Goodreads scraping.\n\n| Source | Auth | Used for |\n|--------|------|----------|\n| [OpenLibrary](https://openlibrary.org) | None | Primary: authors, books, editions, covers, ISBN |\n| [Google Books](https://developers.google.com/books) | API key (free) | Enrichment: descriptions, ratings |\n| [Hardcover.app](https://hardcover.app) | None (public GraphQL) | Enrichment: community ratings, series, wishlist |\n| [DNB](https://www.dnb.de/) | None (public SRU) | German-language descriptions, language, year, publisher; can be promoted to **primary** |\n| [Audnex](https://api.audnex.us) | None | Audiobook narrator, duration, cover by ASIN |\n| [Audible](https://audible.com) | None | Supplemental audiobook author lookup — pulls ASINs OL/Hardcover miss |\n\nCover images are fetched and cached server-side under `\u003cdataDir\u003e/image-cache/` (30-day TTL). Every `imageURL` is rewritten to `/api/v1/images?url=...` before leaving the server — the browser never contacts third-party image hosts directly.\n\n**Discover** — personalised recommendations on the **Discover** page from multiple signals: next-in-series for what you're reading, new releases from monitored authors, genre similarity (≥ 20 books in library), OpenLibrary subject popular picks, and Hardcover wishlist cross-reference. Recency scoring is relative to the *median* publication year of your library, so backlist readers aren't penalised. Hard-filters owned, dismissed, excluded-author, wrong-language, fewer-than-50-ratings, sub-3.0-rated, and omnibus titles. Dismiss / exclude actions persist.\n\n**Migration** — upload `readarr.db` directly (authors re-resolved against OpenLibrary since `bookinfo.club` is dead; indexers, download clients, and blocklist port structurally), or paste a newline-separated list of author names. CLI: `bindery migrate {csv,readarr} \u003cpath\u003e` for first-time bulk imports without opening the UI.\n\n**Operations**\n- **Authentication** — first-run setup creates an admin account (argon2id, signed session cookies). Four modes: **Enabled** / **Local only** (bypass for private IPs) / **Disabled** / **Proxy** (trust upstream `X-Forwarded-User` from a configured trusted proxy — drop-in for Authelia / Authentik / oauth2-proxy). Per-account API key, per-IP login rate limiting, CSRF double-submit (API-key clients exempt).\n- **OIDC** — native Authorization Code + PKCE with multi-provider support. Pre-configured for Google, GitHub (via Dex), Authelia, and Keycloak; identifies users by stable `(issuer, sub)` so email/username changes don't break logins.\n- **Multi-user mode** — per-user libraries, monitored authors, profiles, and downloads. Admin role manages indexers / download clients / users; standard users see only their own catalogue. Local, OIDC-provisioned, or forward-auth-mapped.\n- **Webhook notifications** for grab / import / failure (pipe to Apprise, ntfy, Home Assistant, Discord, Slack via proxies). **Tags** scope indexers / profiles / notifications to specific authors. **On-demand SQLite backups.** **Persistent log viewer** in Settings → Logs with runtime DEBUG toggle.\n- **Arr-compatible queue** at `GET /api/queue` for [Harpoon](https://github.com/harpoon-io/harpoon) and other *arr-aware tools — pagination, sort, live size, status, client, remote ID, protocol.\n\n**UI**\n- Modern React 19 + TypeScript + Tailwind CSS SPA with deep-linkable routed `/book/:id` and `/author/:id` pages.\n- Light / dark themes (respecting `prefers-color-scheme` first paint), grid / table view toggles, mobile-friendly responsive layout, hamburger nav, agenda-style mobile Calendar.\n- Full pagination, search, filter, and sort on every list page; preferences persist to `localStorage`.\n- 7 languages — English, French, German, Dutch, Spanish, Filipino (Tagalog), Indonesian — auto-detected from the browser, override in Settings.\n- **OPDS 1.2 catalogue** at `/opds/v1.2/` for KOReader, Moon+ Reader, and other reading apps. HTTP Basic auth with the API key as the password.\n\n**Packaging** — single Go binary with the React frontend embedded via `go:embed`. Distroless container (non-root, read-only rootfs, all caps dropped, RuntimeDefault seccomp). Helm chart for ArgoCD / Flux. Pure-Go SQLite via `modernc.org/sqlite` — no CGO, no external database.\n\n## Quick Start\n\n### Docker\n\n```bash\ndocker run -d \\\n  --name bindery \\\n  -p 8787:8787 \\\n  -v /path/to/config:/config \\\n  -v /path/to/books:/books \\\n  -v /path/to/downloads:/downloads \\\n  ghcr.io/vavallee/bindery:latest\n```\n\nOpen \u003chttp://localhost:8787\u003e, follow the first-run setup to create the admin account, and you're in.\n\n### Docker Compose\n\n```yaml\nservices:\n  bindery:\n    image: ghcr.io/vavallee/bindery:latest\n    container_name: bindery\n    ports:\n      - 8787:8787\n    volumes:\n      - ./config:/config\n      - /media/books:/books\n      - /media/downloads:/downloads\n    environment:\n      - BINDERY_LOG_LEVEL=info\n    restart: unless-stopped\n```\n\n### Other install methods\n\nPre-built binaries for Linux / macOS / Windows (amd64, arm64, armv7, armv6), Kubernetes (Helm chart at `charts/bindery/`), and the Unraid Community Applications template are all covered in **[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md)** — including UID/GID setup, path remapping for multi-container deployments, the full environment-variable reference, and per-version upgrade notes.\n\n## Configuration\n\nBindery is configured through the web UI under **Settings** — indexers, download clients, quality profiles, naming, notifications, auth, and everything else runtime-tunable lives there. A small set of bootstrap-only knobs are environment variables:\n\n| Variable | Default | Purpose |\n|----------|---------|---------|\n| `BINDERY_PORT` | `8787` | HTTP server port |\n| `BINDERY_DB_PATH` | platform-default | SQLite database path |\n| `BINDERY_DATA_DIR` | platform-default | Config directory (backups, image cache, secrets) |\n| `BINDERY_LIBRARY_DIR` | `/books` | Imported ebook destination |\n| `BINDERY_AUDIOBOOK_DIR` | inherits library | Imported audiobook destination |\n| `BINDERY_DOWNLOAD_DIR` | `/downloads` | Where the download client deposits completed jobs |\n| `BINDERY_URL_BASE` | _(empty)_ | Reverse-proxy subpath (e.g. `/bindery`) |\n| `BINDERY_PUID` / `PGID` | _(unset)_ | Sanity-check assertions for the container UID/GID |\n\nThe full reference (path remapping, API-key seeding, OIDC, telemetry, rate-limit knobs, cookie-Secure policy) is in **[docs/DEPLOYMENT.md#environment-variables](docs/DEPLOYMENT.md#environment-variables)**.\n\n## Supported integrations\n\n| Category | Implementations |\n|---|---|\n| **Usenet clients** | SABnzbd, NZBGet |\n| **Torrent clients** | qBittorrent, Transmission, Deluge |\n| **Indexers** | Newznab (NZBGeek, NZBFinder, NZBPlanet, DrunkenSlug, …), Torznab (Prowlarr, Jackett, direct endpoints), with per-indexer category overrides |\n| **Notifications** | Generic webhooks — pipe to Apprise / ntfy / Home Assistant / Slack / Discord |\n| **Authentication** | Local (argon2id), API key, OIDC (Google, GitHub via Dex, Authelia, Keycloak, …), forward-auth proxy |\n| **Reading apps** | OPDS 1.2 catalogue at `/opds/v1.2/` (KOReader, Moon+ Reader, Aldiko, …) |\n\nAll download clients support **Use SSL** and **URL Base** for connections through a reverse-proxy subpath.\n\n## Architecture\n\nBindery is a single Go binary (chi router, distroless container) with the React 19 + TypeScript frontend embedded via `go:embed`, talking to SQLite in WAL mode through the pure-Go `modernc.org/sqlite` driver — no CGO, no external database, no sidecars.\n\n```\n   Newznab / Torznab\n      indexers\n         │\n         ▼\n┌────────────────────────────┐\n│         Bindery            │──► SABnzbd / NZBGet / qBittorrent / Transmission / Deluge\n│  Go backend + React SPA    │──► /books/ library\n│  SQLite (WAL mode)         │──► Webhook notifications\n└────────────────────────────┘\n    ▲                    ▲\n    │                    │\nOpenLibrary      Google Books, Hardcover.app, DNB, Audnex, Audible\n (primary)                 (enrichers)\n```\n\nComponent breakdown, package layout, concurrency model, and design rationale are in **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)**.\n\n## API\n\nEvery feature is exposed under `/api/v1/*`, with an arr-compatible `/api/queue` for external tools and an OPDS catalogue at `/opds/v1.2/`. Quick taste:\n\n```bash\n# Add an author by OpenLibrary ID and start monitoring\ncurl -X POST -H \"X-Api-Key: $KEY\" -H \"Content-Type: application/json\" \\\n  -d '{\"foreignAuthorId\":\"OL23919A\",\"monitored\":true,\"searchOnAdd\":true}' \\\n  http://bindery:8787/api/v1/author\n\n# List wanted books\ncurl -H \"X-Api-Key: $KEY\" \"http://bindery:8787/api/v1/book?status=wanted\"\n```\n\nThe full endpoint catalogue, authentication rules (API key, session cookie, local-only, OIDC, proxy), CSRF semantics, and integration examples are in **[docs/API.md](docs/API.md)**.\n\n## Documentation\n\n| Topic | Where |\n|-------|-------|\n| **Quickstart** — first author to first grab in 10 minutes | [Wiki](https://github.com/vavallee/bindery/wiki/Quickstart) |\n| **Deployment** — Docker, Compose, k8s/Helm, binary, UID/GID, env vars, upgrades | [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) |\n| **Architecture** — components, data flow, dependencies | [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) |\n| **API** — REST endpoints, auth, integration patterns | [docs/API.md](docs/API.md) |\n| **ABS import** — setup, path remap, review queue, rollback, matching behavior | [docs/abs_import.md](docs/abs_import.md) |\n| **Enhanced Hardcover series** — token setup, series linking, catalog diffs, missing-book fill | [docs/Hardcover-Series-Wiki.md](docs/Hardcover-Series-Wiki.md) |\n| **Roadmap** — planned work and explicitly-out-of-scope items | [docs/ROADMAP.md](docs/ROADMAP.md) |\n| **Contributing \u0026 CI checks** — dev setup, full quality/security matrix, local check suite | [CONTRIBUTING.md](CONTRIBUTING.md) |\n| **Changelog** — release notes | [CHANGELOG.md](CHANGELOG.md) |\n| **Reverse-proxy \u0026 SSO setups** — Traefik / Caddy / Nginx / Authelia / Authentik recipes | [Wiki](https://github.com/vavallee/bindery/wiki/Reverse-proxy-and-SSO) |\n| **Troubleshooting** — permission-denied, path-remap, import failures | [Wiki](https://github.com/vavallee/bindery/wiki/Troubleshooting) |\n| **Indexer \u0026 download-client recipes** — NZBGeek / DrunkenSlug / Prowlarr / Jackett / SAB / qBit tips | [Wiki](https://github.com/vavallee/bindery/wiki/Indexer-and-downloader-recipes) |\n| **Migrating from Readarr** — step-by-step with known failure modes | [Wiki](https://github.com/vavallee/bindery/wiki/Migrating-from-Readarr) |\n\n## Community\n\n- **Discord** — real-time help, setup questions, release chat: [discord.gg/RpuYYRM9cZ](https://discord.gg/RpuYYRM9cZ). The `#support` channel is the best place to ask; `#changelog` is updated on every release. The three read-only voice channels at the top of the server show live active-install count, latest release, and GitHub star count, refreshed from the telemetry API every 10 minutes.\n- **GitHub Issues** — bug reports and feature requests: [issues](https://github.com/vavallee/bindery/issues).\n- **GitHub Discussions** — open-ended design questions, show-and-tell, integration recipes: [discussions](https://github.com/vavallee/bindery/discussions).\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\n\u003cp\u003e\n  \u003ca href=\"https://github.com/vavallee/bindery/security/code-scanning\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/vavallee/bindery/security.yml?branch=main\u0026label=security%20scans\u0026logo=github\" alt=\"Security scans\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://securityscorecards.dev/viewer/?uri=github.com/vavallee/bindery\"\u003e\u003cimg src=\"https://api.securityscorecards.dev/projects/github.com/vavallee/bindery/badge\" alt=\"OpenSSF Scorecard\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/vavallee/bindery/security/dependabot\"\u003e\u003cimg src=\"https://img.shields.io/badge/Dependabot-enabled-brightgreen?logo=dependabot\" alt=\"Dependabot\" /\u003e\u003c/a\u003e\n  \u003ca href=\"SECURITY.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/security-policy-blue\" alt=\"Security policy\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nBindery holds API keys, reaches LAN services, and writes to disk — we take that seriously. Every push and weekly cron runs gosec, govulncheck, Semgrep, gitleaks, Trivy, Grype, Dockle, Syft, ZAP baseline, and OpenSSF Scorecard, with findings published as SARIF in GitHub's Security tab. Release images ship with SLSA build provenance and Syft SBOMs. In-app: SSRF guards on every outbound URL, hardened response headers (CSP, frame-deny, referrer-policy, auto-HSTS), distroless non-root read-only rootfs container with all caps dropped, and digest-pinned base images.\n\nTo report a vulnerability, follow the process in **[SECURITY.md](SECURITY.md)**. The full threat model and verification recipes live on the [wiki Security page](https://github.com/vavallee/bindery/wiki/Security).\n\n## Telemetry\n\nBindery sends one anonymous ping per day to [api.getbindery.dev](https://api.getbindery.dev) so the maintainer can count active installs. The payload contains a random `install_id` (generated on first run), the binary `version`, `os`, and `arch` — no hostnames, IP addresses, library contents, or personal data. The response carries the latest published version, used for in-app update notifications. Opt out with `telemetry.enabled: false` in **Settings → General**, or `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/ROADMAP.md](docs/ROADMAP.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://wiki.servarr.com/) for pioneering the monitor-search-download-import pattern\n- [OpenLibrary](https://openlibrary.org) for free, open book metadata\n- The Readarr project for the original vision, even though the implementation couldn't be sustained\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvavallee%2Fbindery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvavallee%2Fbindery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvavallee%2Fbindery/lists"}