What this release is
Phase 3 of the cover-normalization design — the hot read path. The cover-rendering pipeline is now ready end-to-end on the server. Browsing UIs that consume it are still Phase 4-5 work; today operators can hit GET /cover/<id>/preview directly with curl to see what's coming.
What you get on upgrade
- New
GET /cover/<id>/previewendpoint: returns a JPEG padded to the user's e-reader aspect ratio, cached on disk. Same auth + visibility as the existing/cover/<id>raw endpoint. - ETag + 304: same browser/CDN behaves as raw covers.
- Disk cache at
/config/.cwa-preview-cache/with hourly LRU sweep keeping it underCWA_PREVIEW_CACHE_MAX_MB(default 1024 MB). - New s6 service
cwa-preview-cache-cleanupruns the sweep on a schedule. - Existing Kobo sync + raw
/cover/<id>are unchanged.
Pull image
docker pull ghcr.io/new-usemame/calibre-web-nextgen:v4.0.53
Or use :latest.
What's coming next
- Phase 4: Cover-editor lock + apply-to-all UI controls.
- Phase 5: Settings checkbox + multi-select bulk-apply UI. The browse views start consuming the new endpoint and the feature is end-user-visible.
Full design: notes/COVER-NORMALIZATION-DESIGN.md.
Configuration knobs (env vars)
| Env var | Default | Effect |
|---|---|---|
CWA_PREVIEW_CACHE_MAX_MB
| 1024
| Cache size cap. Sweeper evicts oldest-atime files until under cap. |
CWA_PREVIEW_CACHE_SWEEP_INTERVAL
| 3600
| Seconds between sweeps. |
CWA_PREVIEW_CACHE_INITIAL_DELAY
| 120
| Seconds before the first sweep on container boot. |
Technical detail
51 new unit tests, all green. Live container verified: cache hit is 23× faster than cold miss; valid JPEG output; If-None-Match returns 304; sweeper runs cleanly. Full report: notes/PHASE-3-VERIFICATION-2026-05-13.md.
Stampede protection: 20 simultaneous requests for the same uncached tile cause only one engine call — confirmed by a 20-thread barrier-synchronized test. No thundering-herd on cold cache.
CI passed on first run (no --admin override) thanks to the v4.0.52 deflake.