Skip to content

New collections#12

Merged
argyleink merged 9 commits intomainfrom
new-collections
Jan 26, 2026
Merged

New collections#12
argyleink merged 9 commits intomainfrom
new-collections

Conversation

@argyleink
Copy link
Collaborator

@argyleink argyleink commented Jan 23, 2026

Screenshot 2026-01-22 at 7 46 15 PM Screenshot 2026-01-22 at 7 46 28 PM Screenshot 2026-01-22 at 7 46 35 PM

Summary by CodeRabbit

  • New Features

    • Collections feature to browse episodes by topic (e.g., LLMs, AI/ML, TypeScript, Accessibility, CSS, Testing)
    • Collections index with visual previews and per-collection detail pages showing related episodes and pagination
    • New Collections navigation link for quick access
  • Accessibility / Navigation

    • Dynamic breadcrumb construction reflecting current path (including collections)
  • Style

    • Improved grid sizing for collection layouts when supported by the browser

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
www-starpod Ready Ready Preview, Comment Jan 23, 2026 3:47am

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

Adds a podcast collections feature: static collection definitions, keyword-based scoring utilities, transcript analysis tooling, computed collection augmentation, collection pages and index, navigation link, and related styling and build ignore updates.

Changes

Cohort / File(s) Summary
Configuration
\.gitignore, package\.json
Adds .gitignore entry for src/data/collections.generated.ts and adds tsx (^4.21.0) to both dependencies and devDependencies in package.json.
Static collections data
src/data/collections\.ts
New exported Collection interface and collections: Collection[] with predefined collection metadata and episode slug lists.
Scoring utilities
src/lib/topic-keywords\.ts
New exports: LLM_KEYWORDS, topicKeywords, scoreTopicRelevance(text, keywords), and scoreLLMRelevance(text) for keyword-based relevance scoring.
Runtime collection computation
src/lib/collections\.ts
New module exposing getComputedCollections() and CollectionRuleConfig; merges static collections with transcript-driven scoring, reading episodes and transcript files and augmenting membership by thresholds/keywords.
Transcript analysis script
scripts/analyze-transcripts\.ts
New CLI-style TypeScript script that tokenizes transcripts, computes topic and LLM relevance, aggregates top episodes per topic, and prints collection suggestions.
Pages: collections
src/pages/collections/index\.astro, src/pages/collections/\[slug\]\.astro
New collections index and dynamic collection detail pages: data loading, SEO/meta/schema generation, episode lists, pagination, and UI rendering.
UI & navigation
src/components/InfoCard\.astro, src/components/Breadcrumbs\.astro
InfoCard.astro adds a link to /collections; Breadcrumbs.astro converted to dynamic breadcrumb construction based on URL path.
Styling
src/styles/global\.css
Adds @supports rule for grid-template-rows: subgrid to set .collections-grid row sizing when supported.

Sequence Diagram(s)

sequenceDiagram
    participant Caller as Build / Page
    participant Lib as getComputedCollections()
    participant Episodes as getAllEpisodes()
    participant FS as Transcript Files (src/content/transcripts)
    participant Scorer as scoreTopicRelevance / scoreLLMRelevance
    participant Result as Augmented Collections

    Caller->>Lib: request computed collections
    Lib->>Episodes: fetch episode metadata
    Episodes-->>Lib: episode list (slugs, numbers, titles)
    Lib->>FS: read transcript files (*.md)
    FS-->>Lib: transcript text per episode
    Lib->>Scorer: compute relevance per collection/topic
    Scorer-->>Lib: relevance scores
    Lib->>Lib: apply thresholds & augment static collections
    Lib-->>Result: return augmented collections array
    Result-->>Caller: consumed by pages / index
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 I hopped through transcripts, sniffed for themes,

keywords gleamed like tiny dreams.
Collections stitched from episode threads,
Pages bloom where curious rabbit treads.
Hop! Browse topics, follow the trails—new finds await on podcast rails.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'New collections' accurately summarizes the primary change: introducing a new collections feature with multiple supporting files and UI components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@scripts/analyze-transcripts.ts`:
- Around line 155-166: The regex built from raw keywords is not escaped and
treats characters like '.' as regex meta-characters (in the loop over
topicKeywords, using lowerText.match(regex)), causing incorrect matches; add a
small helper (e.g., escapeRegExp) that escapes regex metacharacters and use it
when building the regex for each keyword (replace new
RegExp(keyword.toLowerCase(), 'gi') with new
RegExp(escapeRegExp(keyword.toLowerCase()), 'gi')); optionally wrap the escaped
keyword with word-boundaries if you want whole-word matches; update references
in the for-loop where regex is constructed (topicKeywords, lowerText,
wordCounts) to use the escaped form.

In `@src/lib/collections.ts`:
- Around line 1-3: The code currently calls readdirSync(join(...)) which will
throw if the transcripts directory is missing; update the collections loading
logic (the code that uses readdirSync, readFileSync and exports/merges with
staticCollections) to guard against a missing directory by either wrapping
readdirSync in a try/catch or checking fs.existsSync before reading and
returning an empty array when the directory is absent, and likewise avoid
readFileSync on non-existent files (apply the same guard to the block around
lines that use readFileSync). Ensure you reference the same symbols
(readdirSync, readFileSync, join, staticCollections) when making the change so
the collections export gracefully falls back to staticCollections + [] instead
of throwing.

In `@src/lib/topic-keywords.ts`:
- Around line 71-79: In scoreTopicRelevance, keyword strings are used raw in new
RegExp which treats characters like "." as regex metacharacters and lets short
tokens match inside words; fix by escaping regex metacharacters in each keyword
(the variable used to build regex in the loop) before constructing the RegExp,
and for short alpha-numeric tokens additionally wrap the escaped keyword in word
boundaries (\\b) to avoid partial-word matches; update the regex creation logic
where regex is declared so matches correctly reflect literal keyword
occurrences.

In `@src/pages/collections/index.astro`:
- Around line 16-37: collectionsWithEpisodes currently deduplicates artwork
globally using usedImageUrls and seenInGroup which can leave unique empty for a
collection even though eps exist; update the logic after the for-loop that
builds unique (using getImg, seenInGroup, usedImageUrls) to detect when
unique.length === 0 and then populate unique with a sensible fallback: take the
first up to 4 episodes from eps (or map to a show-level image via getImg) so the
collection isn’t rendered as “No episodes”; keep references to the same symbols
(collectionsWithEpisodes, getImg, unique, eps, seenInGroup, usedImageUrls) so
the fallback runs only when no unique images were found and still preserves
global de-duplication behavior for subsequent collections.
🧹 Nitpick comments (2)
src/lib/collections.ts (1)

30-81: Memoize computed collections to reduce repeated transcript scans.
getComputedCollections() is invoked from multiple pages; caching avoids repeated filesystem reads and scoring during build/SSR. If you need live updates in dev, you can gate the cache or add invalidation.

♻️ Optional memoization to reduce repeated work
+let computedCollectionsCache: typeof staticCollections | null = null;
+
 export async function getComputedCollections() {
+  if (computedCollectionsCache) return computedCollectionsCache;
   const allEpisodes = await getAllEpisodes();
@@
-  return staticCollections.map((col) => ({
+  const computed = staticCollections.map((col) => ({
     ...col,
     episodeSlugs: Array.from(membership.get(col.slug)!).sort()
-  }));
+  }));
+  computedCollectionsCache = computed;
+  return computed;
 }
src/pages/collections/[slug].astro (1)

10-30: Avoid recomputing collections per page by passing prev/next in props.
getComputedCollections() runs in getStaticPaths() and again to compute pagination. You can compute prev/next once and pass them through props to avoid extra work.

♻️ Example refactor to compute prev/next in getStaticPaths
 export async function getStaticPaths() {
   const collections = await getComputedCollections();
-  return collections.map((collection) => ({
+  return collections.map((collection, index) => ({
     params: { slug: collection.slug },
-    props: { collection }
+    props: {
+      collection,
+      prevCollection: index > 0 ? collections[index - 1] : null,
+      nextCollection: index < collections.length - 1 ? collections[index + 1] : null
+    }
   }));
 }
 
-const { collection } = Astro.props;
+const { collection, prevCollection, nextCollection } = Astro.props;
@@
-// Find current collection index for pagination
-const computedCollections = await getComputedCollections();
-const currentIndex = computedCollections.findIndex((c) => c.slug === collection.slug);
-const prevCollection = currentIndex > 0 ? computedCollections[currentIndex - 1] : null;
-const nextCollection = currentIndex < computedCollections.length - 1 ? computedCollections[currentIndex + 1] : null;
+// prevCollection / nextCollection provided by getStaticPaths

@argyleink argyleink merged commit 09e99c0 into main Jan 26, 2026
6 checks passed
@argyleink argyleink deleted the new-collections branch January 26, 2026 02:07
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.

2 participants