internetarchive / internetarchive/openlibrary
Epic: Subject page redesign — a guided "genre dashboard"
- Dominant language
- Python
- Stars
- 6.7k
- Forks
- 2k
- Avg merge
- 2d 14h
- Merged PRs (30d)
- 126
Description
Epic: Subject page redesign — a guided "genre dashboard"
## Summary
Rework `/subjects/` from a utilitarian, undifferentiated catalog dump into a
guided, bookstore-style **genre dashboard**: an editorial masthead, signal-driven
"notable" content, curated collection rails, and better wayfinding — while staying
scalable across the long tail of subjects and keeping the page's existing librarian
and research workflows intact.
**Genres are the priority beneficiary** (this dovetails with the upcoming genre
taxonomy upgrade), but the improvements apply to subject pages generally.
This is a tracking/epic issue. It captures the vision, the design principles, and a
**phased checklist** — each phase is meant to spin off into its own small,
independently reviewable issue/PR. Please don't try to land this as one change.
### Context & prior art
- **Exploratory draft PR (not for merge):** #13062 — bundles a full redesign for
reference. Treat it as a sketch of the destination, not the implementation plan.
- **Mock (Science Fiction):** editorial hero + stat row + fanned covers, curated
themed shelves, a grouped subgenre sidebar, "notable authors" cards with a
representative title, and a tightened "keep exploring" section.
- The dev environment has sparse Solr data and no real cover backend, so evaluate
the *structure and framing*, not populated content.
---
## Design principles
1. **Curation over enumeration.** Answer reader intents ("what's a good first
taste?", "what's the canonical starting point?") rather than slicing the catalog
into eight near-identical rails.
2. **Editable, not one-off.** The one-off SF blurb in the mock is not the model.
The proposed direction is that authored content (hero blurb, curated picks,
section copy) lives in an **in-app, wiki-editable** place, not in code — so a
librarian can change a blurb without a deploy. We already have a natural hook:
subjects with an associated **`/type/tag`** entity are Infogami-editable today
and the type already carries `tag_description` and `body` fields, with an
Edit/Create flow wired into `subjects.html` — so authoring could build on that
rather than inventing new infra.
_This is a proposal, not a settled decision — **push back if you disagree.**_
Config-in-code (contributor PRs) or a hybrid (generated defaults + editable
overrides) are viable alternatives; if in-app editing is the wrong tradeoff for
scale, maintenance, or abuse reasons, say so here.
3. **Scale via graceful fallback.** Most subjects will never be hand-authored.
Every section must degrade cleanly to a generated / signal-driven default (or
hide entirely) when there's no authored content and no data. Under-configured
subjects must never look broken.
4. **Don't silently drop existing features.** Several current features serve
librarians, researchers, and SEO/internal-linking. Each must be an explicit
keep / relocate / retire decision, not a side effect.
5. **Define rail selection & ordering up front.** Before any curated-rail phase
ships, its phase must specify *which* rails appear for a given subject, in *what
order*, and how we *avoid content overlap* between rails. Ordering signals
(recency, availability, popularity) and overlap rules are part of the phase, not
a later afterthought. (Deeper personalization — e.g. surfacing fast-changing
rails higher for frequent visitors — is an open question to explore within that
phase.)
---
## Phases
Each unchecked item below should become its own issue. Rough dependency order, but
several are independent and can proceed in parallel.
### Phase 1 — Notable authors ⭐ recommended first task
Self-contained, high-visibility, no new infra.
- [x] Replace "Prolific Authors" (ranked by raw `author_key` facet count in
`subjects.py`) with **signal-ranked "Notable authors"** — authors whose
pages/works show activity indicating importance for the subject.
- [x] Each author card shows a **portrait** and a **representative/notable work**
("Isaac Asimov — *Foundation* and 3 more"), not a raw book count.
- [x] Graceful fallback when an author has no photo or no clear notable work.
- Touches: `openlibrary/plugins/worksearch/subjects.py`, `macros.ProlificAuthors`
(→ a new `SubjectAuthors` macro), author-photo lookup.
### Phase 2 — Header / masthead
> **Scope note:** the mock's fanned-out set of six book covers is **not required
> for the initial release**. The initial release is the subject name, a short
> blurb, and the stat row (works count, years in print) — i.e. the items already
> captured in the to-dos below.
- [ ] Stronger **serif title** + short blurb (blurb pulled from the editable Tag
`tag_description`/`body`; generated/empty fallback otherwise).
- [ ] **Stat row:** works · readable-now · **years-in-print**.
- [ ] Make "years in print" *actually useful* — filter outliers so a single
mis-dated edition doesn't produce "1500–2025". Define the filtering rule.
- Touches: `subjects.py` (`work_count`, `ebook_count`, `publishing_history`),
`subjects.html`.
### Phase 3 — Tighten "Keep exploring"
- [ ] Cap and rank the related-tag lists instead of dumping every facet; show a
curated, relevance/volume-ranked subset with a "show more" affordance.
### Phase 4 — Notable / featured works at the top
- [ ] Surface a small set of standout works visually near the header (the "fanned
covers" / hero cover stack in the mock). Editable pick with a signal-driven
fallback.
### Phase 5 — Carousel wrapper component
- [ ] A reusable carousel wrapper with a **header + subtitle + optional tags/badges**
baked in (so every rail gets consistent editorial framing).
- [ ] Coordinate with the separate `ol-carousel` (`OlCarousel.js`) upgrade
(uniform 2:3 covers, denser layout, paged-in cover loading).
### Phase 6 — Curated collection rails + selection/ordering logic
- [ ] Themed shelves (reader favorites, award winners, "short standalones", "begin
a series", "read it right now", "just published").
- [ ] **Per principle 5:** define which rails show per subject, their order, overlap
avoidance, and ordering signals — as part of this phase.
- [ ] Sparse-rail suppression (hide a rail below a `min_books` threshold).
### Phase 7 — Editable per-subject content (authoring)
- [ ] Extend the `/type/tag` authoring flow so librarians can edit the hero blurb
and (later) curated picks in-app, no deploy required.
- [ ] Ensure the Edit affordance is discoverable from the redesigned page.
### Gated on the genre taxonomy upgrade
- [ ] **Subgenre sidebar / subgenre navigation** — the grouped, described, icon'd
"Genres" wayfinding sidebar. **Blocked** on the genre taxonomy work (we don't
yet have subgenres or genre descriptions). Track that dependency here; don't
start until the taxonomy data exists.
---
## Key files (current state)
| Area | Location |
|---|---|
| Subject data / SolR | `openlibrary/plugins/worksearch/subjects.py` (`SubjectEngine`, `get_subject_async`) |
| Page template | `openlibrary/templates/subjects.html` |
| Existing macros | `PublishingHistory`, `RelatedSubjects`, `ProlificAuthors`, `QueryCarousel` |
| Carousel component | `openlibrary/components/lit/OlCarousel.js` |
| Editable entity | `/type/tag` — `openlibrary/core/models.py` (`Tag`), form in `openlibrary/templates/type/tag/` |
## Related
- Draft reference PR: #13062 (not for merge)
- Genre taxonomy upgrade: _(link when the tracking issue exists)_
Contributor guide
Assessment
This issue has not been assessed yet.