Display the running build version at the bottom of the sidebar (e.g. v0.2.11
for releases, v0.2.11.3 for dev builds), linking to the changelog. New
version.py exposes display_version(); shared_templates.py registers it as the
app_version Jinja global; main.py adds /api/version.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Dark/Sepia theme toggle to the reader's reading-settings drawer for
easier long-form reading. Sepia uses a warm paper background with dark brown
text via a :root[data-theme="sepia"] palette in theme.css. Text colour is now
stored per theme with theme-specific swatch sets; the old single key migrates
into the dark slot. An inline head script applies the saved theme before paint
to avoid a flash.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The release commit accidentally pulled in .claude/worktrees/ and
.codex via git add -A in build-and-push.sh. Add them to .gitignore
and remove from the index. Also drop unused version.txt and the
no-longer-used .last-branch entry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reader: monotonic reading progress across devices — saved position only
advances, never rewinds (explicit Mark as read/unread still resets).
Plus the previously uncommitted v0.2.5–v0.2.8 work (FlareSolverr scraping,
Book Info pages, deferred chapter add/delete, scanned/uploaded backup
counters, Dropbox upload tuning, four inline editor formatting buttons,
migration logging, "New view" needs_review fix, consecutive break-image
collapsing, and the related TECHNICAL.md updates).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- IntersectionObserver defers both cover images and placeholder canvas
drawing until cards enter viewport — eliminates 1000+ upfront ops
- ETag on /library/list: browser gets 304 Not Modified when nothing changed
- Single DOM pass in renderBooksGrid/renderDuplicatesView/renderSeriesDetail:
card.querySelector replaces second iteration with 500+ getElementById calls
- book_tags joined via json_agg in main query, removing separate SELECT + Python merge
- loadLibrary: error handling prevents silent failures showing as infinite loading
- Delete TODO-PERF-library-load.md (all four bottlenecks resolved)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>