Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 0 additions & 67 deletions .github/workflows/build-and-publish-docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,70 +113,3 @@ jobs:
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}${{ matrix.image_name_suffix }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true

# Create aliases for backwards compatibility
create-aliases:
needs: build-and-push-images
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
permissions:
contents: read
packages: write
env:
# Legacy name for backwards compatibility (hardcoded so it works after rename)
LEGACY_NAME: calibre-web-automated-book-downloader
steps:
- name: Log in to registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0

- name: Create legacy aliases
run: |
# Current image names (follows repo name)
STANDARD="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"
LITE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-lite"

# Legacy image names (hardcoded for backwards compatibility)
LEGACY="${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.LEGACY_NAME }}"
LEGACY_TOR="${LEGACY}-tor"
LEGACY_EXTBP="${LEGACY}-extbp"

SHA_SHORT=$(echo "${{ github.sha }}" | cut -c1-7)

# Helper function to create alias with all standard tags
create_alias() {
local SOURCE=$1
local ALIAS=$2

# Always create SHA tag
docker buildx imagetools create -t "${ALIAS}:sha-${SHA_SHORT}" "${SOURCE}:sha-${SHA_SHORT}"

if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
VERSION="${{ github.ref_name }}"
VERSION_NUM="${VERSION#v}"
MINOR="${VERSION_NUM%.*}"

docker buildx imagetools create -t "${ALIAS}:latest" "${SOURCE}:latest"
docker buildx imagetools create -t "${ALIAS}:${VERSION_NUM}" "${SOURCE}:${VERSION_NUM}"
docker buildx imagetools create -t "${ALIAS}:${MINOR}" "${SOURCE}:${MINOR}"
docker buildx imagetools create -t "${ALIAS}:${VERSION}" "${SOURCE}:${VERSION}"
else
docker buildx imagetools create -t "${ALIAS}:dev" "${SOURCE}:dev"
fi
}

# Create legacy aliases pointing to current images
# calibre-web-automated-book-downloader → standard image
create_alias "${STANDARD}" "${LEGACY}"

# calibre-web-automated-book-downloader-tor → standard image
create_alias "${STANDARD}" "${LEGACY_TOR}"

# calibre-web-automated-book-downloader-extbp → lite image
create_alias "${LITE}" "${LEGACY_EXTBP}"
2 changes: 1 addition & 1 deletion compose/docker-compose.lite.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
shelfmark-lite:
image: ghcr.io/calibrain/shelfmark-lite:latest
image: ghcr.io/infiniteavenger/shelfmark-lite:latest
container_name: shelfmark-lite
environment:
# EXT_BYPASSER_URL: http://flaresolverr:8191 #If using Flaresolverr
Expand Down
2 changes: 1 addition & 1 deletion compose/docker-compose.tor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Routes all traffic through Tor - requires root startup
services:
shelfmark-tor:
image: ghcr.io/calibrain/shelfmark:latest
image: ghcr.io/infiniteavenger/shelfmark:latest
environment:
FLASK_PORT: 8084
USING_TOR: true
Expand Down
2 changes: 1 addition & 1 deletion compose/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
shelfmark:
image: ghcr.io/calibrain/shelfmark:latest
image: ghcr.io/infiniteavenger/shelfmark:latest
container_name: shelfmark
environment:
PUID: 1000
Expand Down
2 changes: 1 addition & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Example `docker-compose`:
```yaml
services:
shelfmark:
image: ghcr.io/calibrain/shelfmark:latest
image: ghcr.io/infiniteavenger/shelfmark:latest
volumes:
- /path/to/config:/config
- /path/to/books:/books
Expand Down
2 changes: 1 addition & 1 deletion docs/custom-scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ If you run Shelfmark in Docker, the script must exist inside the container. The
```yaml
services:
shelfmark:
image: ghcr.io/calibrain/shelfmark:latest
image: ghcr.io/infiniteavenger/shelfmark:latest
volumes:
- /path/to/your/scripts:/scripts:ro
```
Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Shelfmark is typically deployed with Docker Compose.
1. Download the compose file from the repository:

```bash
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml
curl -O https://raw.githubusercontent.com/InfiniteAvenger/shelfmark/main/compose/docker-compose.yml
```

2. Start the service:
Expand Down
46 changes: 22 additions & 24 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
<img src="src/frontend/public/logo.png" alt="Shelfmark" width="200">

> [!NOTE]
> This project is in a stable state as of May 2026 but is not under active maintenance.
> This is a **fork** of [calibrain/shelfmark](https://github.com/calibrain/shelfmark) that adds the
> automation the upstream project intentionally left out — Hardcover wishlist sync, automatic
> downloading, and Audiobookshelf library-aware de-duplication. All original functionality is
> preserved and full credit goes to the original authors; upstream is in maintenance mode. See
> [Fork Additions](#-fork-additions) for what's different.

Shelfmark is a self-hosted web interface for searching and requesting books and audiobooks across multiple sources. Bring your own sources, metadata providers, and download clients to build a single hub for your digital library. Supports multiple users with a built-in request system, so you can share your instance with others and let them browse and request books on their own.

Expand All @@ -25,6 +29,19 @@ Works great alongside the following library tools, with support for automatic im
- **Real-Time Progress** - Unified download queue with live status updates across all sources
- **Network Flexibility** - Configurable proxy support, DNS settings, and optional Cloudflare handling for protected sources

## 🔱 Fork Additions

This fork adds an optional automation pipeline on top of upstream Shelfmark, configurable under **Settings → Hardcover Sync**. Everything here is **off by default and opt-in**:

- **Hardcover Wishlist Sync** - Automatically pull books from a Hardcover reading shelf (e.g. "Want to Read") into Shelfmark as requests, on a schedule (configurable in minutes or hours) or on demand via a "Sync now" button. Synced requests carry full metadata and cover art.
- **Automatic Downloads** - Auto-approve and download synced books, selecting the best release from a **drag-to-reorder source priority** list. A strict title/author/audiobook-format (and seeder) match guard avoids grabbing the wrong file; anything without a confident match is left as a pending request for manual review.
- **Library-Aware De-duplication** - Check your [Audiobookshelf](https://github.com/advplyr/audiobookshelf) library before adding or downloading a book and skip anything you already own. Fails open (proceeds) if Audiobookshelf is unreachable, so the pipeline never stalls.

> [!TIP]
> **Designed to pair with [ShelfBridge](https://github.com/rohit-purandare/ShelfBridge).** ShelfBridge syncs your Audiobookshelf *listening progress* **up to** Hardcover; this fork closes the loop in the other direction — pulling your Hardcover "Want to Read" shelf **down into** your library and skipping anything you already own. Run both and Hardcover becomes a single hub: mark a book "Want to Read" and it lands in your library automatically; finish listening and your Hardcover status updates on its own.

These build on Shelfmark's existing request and download systems; with all of them disabled, the app behaves exactly like upstream.

## 🖼️ Screenshots

**Home screen**
Expand All @@ -49,7 +66,7 @@ Works great alongside the following library tools, with support for automatic im

1. Download the [docker-compose file](compose/docker-compose.yml):
```bash
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.yml
curl -O https://raw.githubusercontent.com/InfiniteAvenger/shelfmark/main/compose/docker-compose.yml
```

2. Start the service:
Expand Down Expand Up @@ -131,7 +148,7 @@ The full-featured image with all network capabilities included.
#### Tor Routing
Optional Tor support for network privacy:
```bash
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.tor.yml
curl -O https://raw.githubusercontent.com/InfiniteAvenger/shelfmark/main/compose/docker-compose.tor.yml
docker compose -f docker-compose.tor.yml up -d
```

Expand All @@ -149,7 +166,7 @@ A lighter image without the built-in browser automation. Ideal for:
- **Audiobooks** - Using Shelfmark primarily for audiobooks

```bash
curl -O https://raw.githubusercontent.com/calibrain/shelfmark/main/compose/docker-compose.lite.yml
curl -O https://raw.githubusercontent.com/InfiniteAvenger/shelfmark/main/compose/docker-compose.lite.yml
docker compose -f docker-compose.lite.yml up -d
```

Expand Down Expand Up @@ -182,25 +199,6 @@ volumes:

With any authentication method enabled, Shelfmark supports multi-user management with admin/user roles. Users can have per-user settings for download destinations, email recipients, and notification preferences. Non-admin users only see their own downloads and can submit book requests for admin review. Admins can configure request policies per source to control whether users can download directly, must submit a request, or are blocked entirely.

## Project Scope

Shelfmark is a manual search and download tool, the entry point to your book library, not a library manager. It finds books, downloads them, and sends them to a configured destination. That's the full scope.

Shelfmark intentionally does not:

- **Track or manage your library** - it doesn't know or care what you already own
- **Integrate with library software** - what happens after delivery is up to your library tool
- **Monitor authors, series, or new releases** - there is no background automation
- **Queue future downloads** - if a book isn't available now, Shelfmark won't watch for it

These are non-goals, not missing features.

## Contributing

Shelfmark's core feature set is complete. Development focuses on stability, bug fixes, quality-of-life improvements, and refining the search experience. Contributions in these areas are welcome, please file issues or submit pull requests on GitHub.

Feature requests that fall outside the project scope (library integration, automation, collection management) will be closed. If you're unsure whether something fits, open a discussion first.

## Health Monitoring

The application exposes a health endpoint at `/api/health` (no authentication required). Add a health check to your compose:
Expand Down Expand Up @@ -261,4 +259,4 @@ Use of this tool is entirely at your own risk.

## Support

For issues or questions, please [file an issue](https://github.com/calibrain/shelfmark/issues) on GitHub.
For issues or questions about this fork, please [file an issue](https://github.com/InfiniteAvenger/shelfmark/issues) on GitHub. For issues with upstream Shelfmark, see [calibrain/shelfmark](https://github.com/calibrain/shelfmark/issues).
3 changes: 2 additions & 1 deletion scripts/bypasser_permission_lab.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

set -euo pipefail

LATEST_IMAGE="${LATEST_IMAGE:-ghcr.io/calibrain/shelfmark:latest}"
LATEST_IMAGE="${LATEST_IMAGE:-ghcr.io/infiniteavenger/shelfmark:latest}"
# Historical upstream baseline for comparison (the fork has no equivalent old tag).
LEGACY_IMAGE="${LEGACY_IMAGE:-ghcr.io/calibrain/shelfmark:v1.0.2}"
WAIT_SECONDS="${WAIT_SECONDS:-5}"
STARTUP_TIMEOUT_SECONDS="${STARTUP_TIMEOUT_SECONDS:-120}"
Expand Down
Loading