Add Greatest of All Time manga dashboard
This commit is contained in:
1 parent
c8dd46d0fb
commit
5df94db9a3
16 files changed
+2717
-1
No files matched your search
@@ -0,0 +1,24 @@
|
||||
# Shijō Saikō no Manga — Greatest of All Time
|
||||
|
||||
`greatest.html` is a second, single-page dashboard. The Japanese title is **史上最高の漫画**, romanized **Shijō Saikō no Manga** (“greatest manga of all time”). It displays the [research reading map](manga-reading-map-2026-10-09.md) as ranked five-year cohorts from before 1970 through 2025–2026. Each period keeps its own separator and tile grid.
|
||||
|
||||
## Separation and data ownership
|
||||
|
||||
- `greatest/catalog.json` is a versioned, read-only editorial seed in the application image. Entries have stable IDs, debut year, cohort, curator rank, rationale, official source lead, and optional AniList cover/chapter/status metadata. It is **not** part of `library/`, scraper queue, or `data/catalog.json` collections.
|
||||
- `greatest/index.js` validates the seed and performs only exact title/alias matching against the existing library index. A match adds the local cover, chapter count, status and **In library** badge; it never moves or downloads a title.
|
||||
- `data/db.json` holds `greatestRatings[userName][entryId]`. Each account can select `flame`, `good`, `neutral`, or `skip`, or click its current choice to clear it. Existing chapter-version votes are separate. Deleting a user removes their ratings. Include `data/db.json` in backups as before.
|
||||
- The only write route is authenticated `POST /api/greatest/rating` with `{id,rating}` (`null` clears). Authenticated `GET /api/greatest` returns the catalog, per-user choice, valid-user community counts, score, and local-library match. Unknown IDs/ratings are rejected. There is no admin-only gate: every account may vote.
|
||||
|
||||
Within each cohort, **Rank by my vote** sorts flame → good → neutral → skull → unrated; **Rank by everyone** uses `3×flames + thumbs-up − 2×skulls`, with curator rank as the tie-breaker. These are preference scores, not independent critical ratings. The quick chips filter by *your* ratings (or in-library status), even when community sorting is active. The popup shows the full rationale, metadata, official source link, community counts, and a library link where available.
|
||||
|
||||
## Covers and metadata
|
||||
|
||||
The one-time seed is curated from the research document. `node tools/enrich-greatest-catalog.js` is an **optional manual** public-AniList metadata refresh, paced at one request every 1.5 seconds. It only accepts matching manga title and **original serialization year**, leaving uncertain results blank rather than using a sequel or remake cover. The server makes **no AniList calls at runtime**. Browser covers are lazy-loaded from AniList's CDN; a title-letter card remains if a cover is missing or fails. Local library covers take precedence.
|
||||
|
||||
Public catalog chapter counts are often absent; the UI says “Chapters unknown” rather than inventing one. For owned titles, the local library count wins. Status comes from AniList's releasing/finished flag or local library metadata, and may be unknown. Official source links may be publisher editions, chapter services, or an award/info lead; they do not imply all chapters are available in every country. No unverified hoster coverage is claimed.
|
||||
|
||||
## Deployment and QA
|
||||
|
||||
The Docker image now copies `greatest/` as app code; no new Compose service, volume, port, secret, or migration is needed. Rebuild/recreate **reader only** to pick up catalog/UI changes. The scraper and sentinel do not need restarting. Existing `data/db.json` accepts the new `greatestRatings` object without migration.
|
||||
|
||||
Run `npm run test:reader` for catalog/API tests and `node tools/test-greatest-ui.js` for disposable headless-browser QA. The UI fixture blocks remote covers and never contacts the scraper. Manual catalog edits should preserve stable IDs once anyone has voted; changing a title's ID strands its votes.
|
||||
Reference in new issue
Block a user