Browse docs

Library Management

Ingestion, storage, browsing, and re-indexing behavior

Alex indexes PDF and EPUB files from one configured source at a time. A Rust process handles source discovery, hashing, metadata, covers, and database updates independently from the web server.

Local-folder mode

The watcher recursively scans the selected folder at startup and then listens for filesystem events.

  • New files are hashed, parsed, covered, and inserted.
  • Changed files are re-hashed and reprocessed when their contents change.
  • Removed files delete the indexed book row, its generated cover, reading progress, and collection memberships.
  • Files found in the database but missing during startup reconciliation are removed.

For additions and changes, Alex waits until the file size has remained stable for two seconds. This avoids processing a file while it is still being copied.

S3 mode

Alex lists the configured bucket and optional prefix on startup and once per polling interval (60 seconds by default). It compares object keys and ETags with the S3-backed rows in SQLite.

  • Added keys are downloaded for ingestion.
  • Changed ETags trigger content comparison/reprocessing.
  • Removed keys remove their indexed rows and covers.

Book files remain in object storage. When a reader needs bytes, Alex streams the object through its server; browser clients do not need bucket credentials or CORS access.

Supported files and metadata

Only .pdf and .epub files are indexed.

  • PDF — Title and author come from the PDF Info dictionary when available; page count is stored. The filename is the fallback title.
  • EPUB — Alex parses container.xml and the OPF package for title, creator, and description. EPUBs do not have a fixed page count.
  • Deduplication — SHA-256 hashes prevent identical content from being inserted twice; source paths/object keys are also unique.

Covers

All persisted covers are JPEG files:

  • PDF page 1 is rendered at 150 DPI.
  • Embedded EPUB cover art is extracted and re-encoded.
  • If either method fails, Alex creates a 400×600 synthetic cover with the title and author.

Covers live under COVERS_PATH, not in SQLite.

Library browsing

The library loads 24 books at a time and automatically loads more near the bottom of the page.

Search matches title or author using SQLite LIKE matching. The URL keeps the current search/filter/sort state.

Filters

  • Type: All Types, PDF, or ePub
  • Reading status: All, Not Started, Reading, or Completed

Sorts

  • Recent — Added time, newest first
  • Last Read — Current user's last progress update, newest first
  • Title — A–Z
  • Author — A–Z

Now Reading

The Now Reading shelf contains books whose current user's progress status is reading, ordered by last activity. Those books are omitted from the main All Books grid while the shelf is visible so the page does not show duplicates.

Collection detail pages have the same behavior for in-progress books inside that collection.

Live updates

The ingestion process updates a database version value whenever book rows change. Alex's browser client maintains an authenticated Server-Sent Events connection; the server checks that version every two seconds and notifies the UI when new data is available.

Desktop library controls

Under Admin → Library, the Electron app can:

  • Change the local folder
  • Switch between local and S3 modes
  • Save S3/R2/MinIO settings
  • Trigger a rescan
  • Clear indexed books and re-index the current source
  • Reset the desktop app back to onboarding

Changing source mode clears indexed book rows and restarts the watcher. It does not delete source files from the selected folder or bucket.