Added a dashboard screenshot to the README and updated the automated
screenshot generation script to seed realistic reading sessions and
progress history.
Signed-off-by: Chmouel Boudjnah <chmouel@chmouel.com>
Unified the separate devices page and administration panel into a single
settings hub at `/ui/settings`. This simplified navigation by removing
clutter from the sidebar while keeping admin tools accessible to
authorized accounts through dedicated sub-views. Updated documentation,
tests, and screenshots to reflect the new route structure.
Signed-off-by: Chmouel Boudjnah <chmouel@chmouel.com>
Every deployment path set LISEUR_CONTENT_ROOT and LISEUR_LIBRARY_ROOTS.
The server reads LISEUR_CACHE_DIR and LISEUR_FOLDER_ROOTS. Unset,
cache_dir falls back to the relative "cache", which resolves inside the
image -- so on civuole the cover cache was sitting in
/home/nonroot/cache, in the container's writable layer, and `up -d`
threw it away on every update. Exactly what the comment beside the
variable said the variable was there to prevent.
Nothing failed, which is why it lasted: an unread variable is silent
and a discarded cache only costs the covers again. docs/deployment.md
had the right names all along; it was the Dockerfile, compose.yaml, the
systemd unit and CI that drifted.
The cache moves to /data/cache rather than reusing /data/content: that
directory still holds sha256/ and .incoming/ from the store this server
no longer has, and the cover cache should not move in beside them.
The catalog is only as truthful as metadata.db, and that database can
disagree with the disk in either direction. A row whose file is gone
costs a warning on every pass. A book directory Calibre has forgotten is
worse: it is invisible to Calibre, and therefore invisible here, however
plainly it sits on the disk.
The second kind is what a synchronised library produces. metadata.db is
one SQLite file replicated as an opaque blob, so two machines editing it
means one edit is discarded silently, taking its books with it while
their directories survive.
The script sweeps both directions, plus stale format rows and books
claiming a cover that is not there. It opens the database immutable so
it is safe against a library Calibre has open, exits non-zero on
findings so it can run from cron, and prints the calibredb command for
each finding without running it: metadata.db belongs to Calibre.
Portable to macOS, which has neither find -printf nor a composed
filename on disk where Calibre stored one.
The script still drove the pipeline that is gone: it created a library,
posted eight EPUBs to the upload route and polled ingest jobs until each
one was promoted. None of those exist, so `make screenshots` failed at
the first curl and the README's pictures could not be retaken.
It now does what the README tells you to do — put the books in a
directory and name it — and then waits for the shelf to fill rather than
assuming it has, because the first pass reads eight EPUBs off a cold
page cache and is not instant.
Pictures retaken: the library page carries a folder selector where it
used to carry a library one.
Added a screenshot generation script using a headless browser to capture
UI views, updated the Makefile target, and added the captured images
to the documentation.
Signed-off-by: Chmouel Boudjnah <chmouel@chmouel.com>
Unfinished uploads and interrupted file processing could leave the
content store in an inconsistent state after a restart. The startup
process was updated to perform an automatic recovery pass over stale
uploads before accepting network traffic. Storage configurations were
also updated for container deployments to ensure stored files persisted
safely across upgrades.
Added an automated installation script that detects available container
runtimes, configures either Docker Compose or Podman with systemd, and
walks through initial user and device setup.
Signed-off-by: Chmouel Boudjnah <chmouel@chmouel.com>