book-reader
Browser viewer for books stored as folders of page images. Shows two pages side by side with a 3D page-turn animation, flips with keyboard, mouse wheel or click, and remembers where you stopped in each book.
The library is one folder with a subfolder per series. Every folder inside a
series that contains images is a book, named after its folder. Pages are
sorted in natural order (2.jpg before 10.jpg).
library/
Series A/ <- images here: the main book "Series A"
Extras/ <- another book of Series A
Series B/
Vol 1/
Vol 2/
The library screen (b) shows a grid of series; a series with more than one
book opens to its books, a single-book series opens straight away. /
searches the current grid, Esc goes back.
Usage
Create ~/.config/book-reader.conf:
LIBRARY="/path/to/library"
PORT=8642
Then:
./rc.book-reader start # prints the URL, e.g. http://127.0.0.1:8642/reader.html
./rc.book-reader stop|restart|status
The server is Python's stdlib http.server, bound to 127.0.0.1. Its served
root holds only symlinks to reader.html and the library, nothing is written
into the library. Runtime files live in /tmp/book-reader-$UID.
Start at boot (Slackware)
cp rc.book-reader /etc/rc.d/ && chmod 755 /etc/rc.d/rc.book-reader
Set RUNAS= near the top of the copy to your user name, and add to the
config the path of the viewer, since the copy no longer sits next to it:
READER="/path/to/book-reader/reader.html"
Then in /etc/rc.d/rc.local:
[ -x /etc/rc.d/rc.book-reader ] && /etc/rc.d/rc.book-reader start
and the same with stop in /etc/rc.d/rc.local_shutdown. Started as root,
the script re-executes itself as RUNAS, so the server never runs as root and
reads that user's config.
Reading progress is kept in browser localStorage, which is per origin: keep
PORT fixed or progress starts over.
Keys
| Action | Keys |
|---|---|
| Next spread | Right, Space, PgDn (scroll first in fit-width), l, wheel down, click right half |
| Previous spread | Left, PgUp, Shift+Space, Backspace, h, wheel up, click left half |
| First / last | Home / End |
| Toggle cover-alone offset | c |
| Fit width / fit height | w (fit-width scrolls, wheel flips at the end of a spread) |
| Library | b (Esc closes) |
| Fullscreen | f |
License
Copyright (C) 2026 Danilo M. danix@danix.xyz
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2, as published by the Free Software Foundation. See LICENSE.
Development Approach
This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback.
All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions.
The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability.
