Skip to content

Show "Also free on LibriVox" in About, and ask /meta for books without ids - #289

Merged
KodeStar merged 8 commits into
mainfrom
feat/librivox-l5
Nov 13, 2026
Merged

KodeStar merged 8 commits into
mainfrom
feat/librivox-l5

Conversation

@KodeStar

Copy link
Copy Markdown
Owner

LibriVox L5 (v2.7.0 row 13, LIBRIVOX-PLAN.md).

What

  • BookMetaRecording.librivox?: {id, url?, zip_url?} mirrors the server's additive field (BookMetaLibrivox in src/api/types.ts).
  • The book's About card ends with a quiet "Also free on LibriVox" link (same style as "View on AudioSilo Meta", directly under it), opened through openExternalUrl (new tab on web, in-app browser on native). librivoxUrl shows it only for an absolute http(s) URL with a host, scheme lower-cased (iOS's web browser module compares the scheme case-sensitively). Localised in en, de, es, fr, it, pt.
  • The book page now asks /meta for any loaded, non-episode book when the metadata capability is on (bookPageMetaEnabled), ids or not: the server answers a book without an ASIN or ISBN from its console match (paired server PR). metaEnabledFor (that plus an asin/isbn/generated) still gates the companion, Now card and Previously on, end credits, reveal toast; offline downloads keep only books with ids. An older server answers {matched:false} for a no-id book with no upstream call, so old servers render as before.

Tests
librivoxUrl (http, https, trimmed, blank, javascript:, relative, scheme-less, ftp, bare host, https://[], upper-case scheme); About shown/hidden cases including an older server without the field; book page for a no-id book: unmatched answer renders as before, a console match with librivox shows both links, no request before the book loads or without the capability. Gate: tsc, lint, prettier check, 7548 tests.

Verified live (web player built from this branch, scratch server from the paired branch, live metadata, real Chrome, light and dark at 1440 and 400):

  • A console-matched LibriVox download with no ids: one /meta request; About shows "View on AudioSilo Meta" and "Also free on LibriVox"; the click opens https://librivox.org/johnny-crows-garden-by-l-leslie-brooke/ in a new tab.
  • An unmatched no-id book and a matched retail book: screenshots byte-identical to the build before the gate change; no LibriVox link. No console or CSP errors.
  • Needs a device run: the native in-app browser on iOS and Android.

Reviews: one full review (Fable 5.2 high) and one fix round over the gate change (Opus high).

Follow-ups (to be filed): the companion, Now card, end credits and offline still need an id, so a console-matched no-id book shows no community content there and the companion can still offer an admin Generate; host check for LibriVox-labelled links; a scheme guard in openExternalUrl app-wide.

Pairs with KodeStar/audiosilo-server#374 and KodeStar/audiosilo-docs.

A matched recording in GET /libraries/{id}/meta can now carry an additive
librivox {id, url, zip_url} (LibriVox L5). BookMetaRecording mirrors it, and
the About card adds a quiet link to the recording's LibriVox page under the
other links out, opened in the browser like "View on AudioSilo Meta".
librivoxUrl re-checks that the page is an absolute http(s) URL before the link
leaves the app; without one (an older server, a non-LibriVox recording) the
card renders as before. The label is in all six locales.

Part of LibriVox L5 (v2.7.0 row 13).
BookMetaLibrivox's doc repeated the server-filters, client-rechecks rule that librivoxUrl already documents, so the two could drift. The type now points at the function for it.

Part of LibriVox L5.
A metadata mirror or a custom metadata service can send librivox.url as "HTTPS://librivox.org/...": the server keeps it as written. On iOS the in-app browser tests the scheme by case and refuses it, openExternalUrl swallows the refusal, and the link shows but does nothing when pressed. librivoxUrl now hands the URL on with its scheme lower-cased and the rest untouched.

A URL whose host reads empty ("https://[]/x/") stays refused, now with a test.

Part of LibriVox L5.
…field

CONVENTIONS.md's About entry names the link and its rule (librivoxUrl), and the /meta wire entry names BookMetaRecording.librivox, so the mirror of the server's field is on record beside the others.

Part of LibriVox L5.
The server now answers /meta for a book with neither id from the match an
admin saved in the console, and LibriVox downloads rarely carry either, so
the id gate kept "Also free on LibriVox" off almost every LibriVox book.
The book page asks through a new bookPageMetaEnabled: the metadata flag and
a loaded book that is not an episode. An older server answers matched:false
for such a book without asking upstream, so an unmatched answer renders as
before. Every other surface (companion, reveal toast, Now card, Previously
on, end credits, the offline copy) keeps metaEnabledFor and its id gate, so
nothing that runs for many books asks more.

Part of LibriVox L5.
Neither asks through metaEnabledFor: the series page's anchor picks a book with an ASIN or ISBN (metadataAnchor) and Search's characters the started books, capped (characterBooksToLoad). The gate's doc and CONVENTIONS.md listed the character search as a metaEnabledFor caller.

Part of LibriVox L5.
metaEnabledFor repeated the metadata flag and the never-an-episode rule that bookPageMetaEnabled holds; it now narrows that predicate by the ASIN, ISBN or generated check, so a future exclusion lands on both. The client's /meta doc states what the server answers and leaves which books are asked to meta-gating.ts.

Part of LibriVox L5.
Search's characters ask /meta for started books ids or not, so such a book's characters show there as well as on its page; the offline copy keeps only books that match by id, so offline its page reads as unmatched. metaAnswered's doc names either gate its caller passes.

Part of LibriVox L5.
@KodeStar
KodeStar merged commit 51244b7 into main Nov 13, 2026
1 check passed
KodeStar added a commit to KodeStar/audiosilo-docs that referenced this pull request Nov 13, 2026
…300)

LibriVox L5 (v2.7.0 row 13). Pairs with KodeStar/audiosilo-server#374
and KodeStar/audiosilo-frontend#289.

**User Guide**
- Book page: About can end with **Also free on LibriVox** (opens the
librivox.org page) when the book is matched to a LibriVox recording, and
a book is matched by its ASIN or ISBN or by an admin in the console.
- Recaps and characters, admin Books, admin Server, FAQ, offline
downloads: a console-matched book without an ASIN or ISBN shows its
community details on its book page (and in Search's characters); the
companion, Home's cards, the end credits and downloaded copies still
need an identifier. What a lookup sends now includes the matched
community entry.

**Developer docs**
- API reference: `/meta`'s lookup order (identifiers, then the recorded
match in `book_matches`), the optional `recording.librivox {id, url?,
zip_url?}` (2.7.0, additive; links only absolute http(s), never built
from the id), the first-recording fallback, the unmatched and 500 rows,
`/meta/cover`, and `/next`'s community step staying identifier-only.
- Configuration and data model: the `m:<work>/<recording>` cache keys;
how `/meta` uses `book_matches`.
- Cross-repo contract, frontend state and data ("Two gates":
`bookPageMetaEnabled` and `metaEnabledFor`), book page (`librivoxUrl`),
offline, podcasts, Bridge attachments, web UI: wording brought in line.

**Screenshots:** none. The screenshot seed's LibriVox books have no
identifiers and no console match, so the link never shows in the
pipeline; follow-up docs#299. The feature was verified live in the web
player on the paired branches (see fe#289).

**Gate:** `npm run build` green. **Review:** one docs review (Opus
high).

Follow-up outside this repo: the site's metadata page copy, site#67
(with the 2.7.0 release).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant