Commit Graph
13 Commits
Author SHA1 Message Date
tim 03ed1a69cb Stack the story and chapter lists on a phone instead of scrolling sideways
Each table had six columns, which squeezed down to unreadable widths on a
narrow screen and forced horizontal scrolling.

Below 600px, each row becomes a bordered card. The main value (the story
or chapter title) stays unlabelled at the top, and every other value gets
a small label in front of it, taken from its column heading.

The chapter table's "select all" checkbox lived in the table header,
which mobile now hides in favour of the per-row labels. It moves into
the sticky actions bar above the list instead, next to the buttons that
already act on the selection.
2026-09-27 23:38:28 +02:00
tim 407f67622b Update Chapters list to make modifying a chapter take less scrolling. 2026-09-27 23:38:28 +02:00
tim 5ef68fb240 Make the metadata fields readable on a phone
Each field was a row of a four-column table: name, lock, value and the
site's current value. On a narrow screen the columns squeezed the
inputs down to a few characters wide.

Each field is now a card with its name and lock on one line and the
input below at full width. The site's value shows only when it
differs, folded behind a line that opens on tap, instead of always
taking its own column. The lock is a labelled toggle instead of a
bare checkbox, and Save stays disabled until something changes.

On a wide screen, the label sits beside the field instead of above
it, and a single-line input no longer stretches to fill the card.
2026-09-27 23:38:28 +02:00
tim 1a10fe53f3 Add single-user local authentication 2026-09-27 23:38:28 +02:00
tim 75cc0464a2 Add README.md and AGENTS.md 2026-09-27 23:38:28 +02:00
tim 7c61bbd1e4 Add the container image and compose file
Gunicorn runs one worker with threads, because the job threads run
inside it. The compose file mounts only CWA's ingest folder and the
config folder.
2026-09-27 23:38:28 +02:00
tim 2f4271314b Add the web interface
Plain HTML, CSS and JavaScript modules, with no build step. Hash routes
and relative URLs make it work under any path. The job list is polled:
every 2 seconds while a job runs, and less often otherwise.
2026-09-27 23:38:28 +02:00
tim 09d6b76a17 Add the JSON API and logins
Logins follow shelfmark: none, CWA accounts, or a reverse proxy header.
CWA accounts are checked against the OPDS feed, with a lockout after
repeated wrong passwords. An API key works in every mode, and changes
need an X-Requested-With header or the key. URL_BASE serves the app
under a path prefix.
2026-09-27 23:38:28 +02:00
tim 49cd18a09f Run download jobs and deliver books to CWA
Jobs download new chapters, recheck chapters, replace the book, update
metadata or rebuild from stored chapters. Locked metadata fields keep
their values. A scheduler queues updates. An update finds the library
book of a story through CWA, and fails with an error if it cannot, so
that it never makes a duplicate book.
2026-09-27 23:38:28 +02:00
tim 312dc3efc5 Find books through CWA's OPDS feed and use its ingest folder
Bindery mounts no CWA database. It searches the OPDS feed by title and
reads the story URL inside each candidate epub to find the library book.
Updates go to the ingest folder with a .cwa.json sidecar, so CWA replaces
the epub of the existing book.
2026-09-27 23:38:28 +02:00
tim c30622e3a0 Download stories and build epubs with FanFicFare
FanFicFare adapters fetch metadata and chapters, and its epub writer
builds each book from the store. Environment variables configure the
app, and a default personal.ini is copied to the config folder on first
start.
2026-09-27 23:38:28 +02:00
tim 6c2574cf0f Store chapters, merge chapter lists, diff and apply rules
The SQLite store keeps every chapter revision, so a chapter that the site
removes stays in the book. The merge puts new chapters after the chapter
that comes before them on the site. Diffs compare text, not HTML, and
replacement rules run on chapter HTML when a book is built.
2026-09-27 21:23:20 +02:00
tim ee59917257 Set up the Python project
Apache-2.0, the same license as FanFicFare. uv manages the dependencies,
and ruff and pytest run from pyproject.toml.
2026-09-26 14:40:15 +02:00