internetarchive / internetarchive/openlibrary
Epic: 'Continue Reading' Flow & Auto-Add Prompts
- Dominant language
- Python
- Stars
- 6.7k
- Forks
- 2k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 138
Description
# Epic: "Continue Reading" Flow & Auto-Add Prompts
## Summary
New patrons land on an empty My Books page — the Loans carousel just says "No books are on this shelf," with no path back to value. We know populated shelves correlate strongly with retention, so this Epic closes that gap with a **"Continue Reading"** shelf on My Books plus an **Auto-Add Prompt Modal** that fires whenever a patron borrows or reads a book. The moment a patron has touched one book, their dashboard should already look alive.
Two structural problems drive the empty state today and motivate the sub-tasks below:
- **Short-term borrows disappear.** Most loans are ~1hr; once expired, they vanish from the active dashboard with no "pick up where you left off" surface.
- **No local fallback.** A patron who isn't logged in, or who opts out of public shelves, currently leaves zero trace we can build a dashboard from.
Phases 4 and 5 will proceed conditional on positive feedback from the community call.
**Close this issue once all five phases below are merged and the unified carousel is live on My Books.**
```mermaid
graph TD
Phase1[Phase 1: Merge Active Loans & History Carousel] --> Phase3[Phase 3: Merge Local Storage into Carousel]
Phase2[Phase 2: Client-Side Read Tracking] --> Phase3
Phase3 --> Phase5[Phase 5: Merge Currently Reading Shelf]
Phase4[Phase 4: Auto-Add Modal UI] --> Phase5
```
---
## Roadmap & Checklist
### [ ] Phase 1: Merge Active Loans & Loan History Carousel (Backend + Template)
Tracked in #13272.
Replace the legacy Loans carousel on My Books with a unified carousel that displays both active CDL loans and past checkouts.
* Fetch active loans (`get_loans_of_user`) and historical loans (`user_borrow_history`).
* Deduplicate books by work OLID.
* Sort by last-access/updated timestamp descending.
* Target files: `openlibrary/templates/account/mybooks.html`, `openlibrary/plugins/upstream/mybooks.py`.
### [ ] Phase 2: Client-Side Read Tracking (Frontend, Local Storage)
Tracked in #13273.
Implement a `localStorage`-backed reading tracker so history is captured even for logged-out or opted-out patrons.
* Intercept click events on "Read", "Borrow", and "Browse" links.
* Push `{ olid, title, coverId, timestamp }` entries to `localStorage.ol_read_history`, capped at the last 20 unique books.
* Target files: `openlibrary/plugins/openlibrary/js/my-books/store/`, `openlibrary/plugins/openlibrary/js/index.js`.
### [ ] Phase 3: Merge Local Storage into Carousel (Frontend Integration)
Tracked in #13274.
Integrate the client-side local storage tracking data with the unified loans carousel on the frontend, showing both backend loans and local history fallback.
* Target files: `openlibrary/templates/account/mybooks.html`, `openlibrary/plugins/upstream/mybooks.py`.
### [ ] Phase 4: Auto-Add Modal Prompt UI (Provisional - Pending Community Feedback)
* Optimistically add to `Currently Reading` on the backend the moment borrow/read is clicked.
* Modal copy: *"Add to Currently Reading? This list is public and powers your activity feed."*
* Action buttons: "Add to bookshelf", "Don't add" with a "Remember my decision" checkbox. Directly link privacy settings inside the modal.
* Ship with built-in Matomo analytics: modal impressions, opt-in rate, opt-out rate.
* Target files: `openlibrary/plugins/openlibrary/js/my-books/ContinueReadingModal.js` [NEW], `static/css/components/continue-reading-modal.css` [NEW].
### [ ] Phase 5: Merge Currently Reading Shelf (Provisional - Pending Community Feedback)
* Merge Currently Reading shelf entries (the third source) into the carousel.
* Deduplicate by work OLID across all three sources (CDL/History, Local Storage, Currently Reading) and sort by last-active timestamp.
* Target files: `openlibrary/templates/account/mybooks.html`, `openlibrary/plugins/upstream/mybooks.py`.
---
## Sub-Issues
- [x] #13272 — Phase 1: Merge Active Loans & Loan History Carousel
- [ ] #13273 — Phase 2: Client-Side Read Tracking (Local Storage)
- [ ] #13274 — Phase 3: Merge Local Storage into Carousel
---
## Next steps
- Phases 1 and 2 can be worked and merged in parallel — neither depends on the other.
- Phase 3 integrates the output of Phase 1 and Phase 2.
- Phase 5 is gated on positive community feedback for Phase 4.
- Close this issue once Phase 5 is merged and the carousel is confirmed live.
## Engineering Standards
- **Python**: double quotes, max line length 162, Ruff-compliant import order.
- **JS**: ESLint-compliant, single quotes, no jQuery in new components.
- **CSS**: Stylelint-compliant — no hex colors, use variables defined in `static/css/`.
- **i18n**: don't split sentences into separate translatable fragments around HTML links. Use single translatable strings with placeholders (e.g. `%(link_start)s` / `%(link_end)s`) so translators can reposition links per target-language grammar.
Contributor guide
Assessment
This issue has not been assessed yet.