site: topics axis + per-source indexes

Topics — the curated subscription layer: 18-value controlled vocabulary
in src/lib/topics.ts, enum-enforced by the content schema on finds and
reviews so unattended runs can't drift it. /topics/ index +
/topics/<t>/ pages with finds first-class alongside reviews, per-topic
RSS feeds that include finds (unlike category/tag feeds), "By topic"
section on /feeds/, Topics footer link and llms.txt section, dev-shim
coverage for the new feed URLs. daily-finds and build-review skills now
classify at capture/graduation time; "giftable" is a tag, never a
topic.

Per-source indexes: /sources/<slug>/ lists every review and find from a
source (catalog ∪ names in content, so retired sources resolve);
find/review colophons link "(more from this source)"; /sources/ cards
link "everything from this source →"; sub-3-item pages noindexed.

Claude-Session: https://claude.ai/code/session_01WZaczDJjL3xZ3u5spsN5AL
This commit is contained in:
2026-07-12 19:39:11 -04:00
parent be7263b912
commit 9e5fce1eb0
21 changed files with 695 additions and 14 deletions
+2
View File
@@ -17,6 +17,8 @@ Built with [Astro](https://astro.build) + MDX.
- **Unified chronological feed** at `/index3/` across reviews + bundles + posts
- **SEO-friendly site footer** with Browse / Collections (live counts) / About link columns and a centered legal line; consistent 76rem page width across the entire site (article prose constrained to a comfortable reading measure inside the wider layout)
- Reviews render as two-line index entries: bold name + muted subtitle (`Cotypist` / *Autocomplete that lives everywhere on your Mac*)
- **Topics — the curated subscription axis**: an 18-value controlled vocabulary in `src/lib/topics.ts` (schema-enum-enforced on finds and reviews, so the unattended pipeline can't drift it); `/topics/` index + `/topics/<t>/` pages where finds are first-class alongside reviews, and per-topic RSS feeds that include finds — unlike category/tag feeds. Facets (`open-source`, `bifl`, `giftable`…) stay tags by design
- **Per-source indexes**: `/sources/<slug>/` lists every review and find surfaced via a source (generated for the catalog all source names in content); find/review colophons link "(more from this source)" next to the source name, and `/sources/` cards link through; thin pages (<3 items) noindexed
- Auto-generated `/categories/<name>/` and `/tags/<name>/` listing pages; tag pages are built from the union of entry and find tags (so every tag linked from a find resolves) and list tagged finds in a secondary section — find-only tag pages with fewer than 3 finds are noindexed until they accumulate content; category pages stay entries-only (finds have no category)
- **Amazon affiliate handling** in `src/lib/affiliate.ts`: outbound links to Amazon (`amazon.com`, `amzn.to`, `a.co`, `smile.amazon.com`) get the configured tracking ID appended automatically; the link gets `rel="sponsored"`, an "Affiliate" badge appears next to it, and a one-line disclosure is shown beneath. Finds and reviews also take an optional `amazonLink` frontmatter field (canonical `/dp/<ASIN>` form) rendered as an "Also on Amazon" link — the capture pipeline populates it when a shortlisted physical product has an exact Amazon match. Add additional marketplace IDs (e.g. `amazon.co.uk`) to the `AMAZON_TAGS` map when needed
- **SEO surface**: single `<SEO>` component owning canonical, Open Graph, Twitter Card, feed autodiscovery, and JSON-LD; per-page structured data (`Review`, `BlogPosting`, `Product`, `Article`, `CollectionPage`, `ItemList`, `BreadcrumbList`, `WebSite` with `SearchAction`, `Organization`); auto-generated `sitemap-index.xml` (excludes `/grid/` and `/index3/`); `robots.txt`; static OG image fallbacks under `/public/og/`; promoted finds canonical to their review