A small local web app that serves a folder of EPUB and PDF books as a Calibre-style cover grid. Point it at a library folder and it shows the covers with title and author, lets you navigate subfolders, search the whole library, and read or download any book by clicking its cover.
- Cover grid — extracts each book's cover and shows it with title/author.
PDFs are marked with a small
PDFbadge; EPUBs are unmarked. - Folder navigation — browse subfolders like a file browser, with breadcrumbs.
- Global search — search the entire library by title, author, or filename.
- In-browser reading — EPUBs open in a paginated reader with themes and font controls; PDFs open in the browser's own PDF viewer.
- One-click download — grab the original
.epubor.pdf. - Fast — covers are thumbnailed and cached on disk; book metadata is indexed in the background, so browsing stays responsive even for large libraries.
PDFs are titled from their filename, not their embedded /Title metadata. In a
real library that metadata is empty or a conversion artifact (Microsoft Word - foo.doc, file:///F|/...) far more often than it is correct, and is occasionally
carried over from a different book entirely — measured across a 20,000-PDF library,
only about 6% of /Title values beat the filename. Skipping it also means indexing
never has to open a PDF, so adding PDFs costs nothing at index time; covers are
rendered lazily on first view and then cached.
- uv
- Python 3.12+ (uv will fetch it if needed)
uv run bookserver /path/to/your/booksThen open http://127.0.0.1:8000.
Options:
uv run bookserver /path/to/your/books --host 0.0.0.0 --port 9000--host— interface to bind (default127.0.0.1; use0.0.0.0to reach it from other devices on your network, e.g. a phone or tablet).--port— port to listen on (default8000).
Caches (cover thumbnails and the metadata index) are stored in your platform's per-user cache directory and never written into the book folders.
uv sync
uv run pytestThe code is split into focused modules under src/bookserver/:
epub.py— parse title/author/cover from an EPUB.pdf.py— render a PDF's first non-blank page as its cover.metadata.py— per-format dispatch, book extensions, and mimetypes.library.py— folder listing, recursive walk, path-traversal guard.covers.py— cover thumbnail cache.index.py— persistent SQLite metadata index and search.app.py— FastAPI routes, templates, and the CLI.