Skip to content

feat(home): catalog awareness on the authenticated home — reframe toward catalog-is-home (chat#1867/#1881 item 1869-r)#1869

Open
sweetmantech wants to merge 1 commit into
mainfrom
feat/home-catalog-awareness
Open

feat(home): catalog awareness on the authenticated home — reframe toward catalog-is-home (chat#1867/#1881 item 1869-r)#1869
sweetmantech wants to merge 1 commit into
mainfrom
feat/home-catalog-awareness

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Reframe + rebase (2026-07-22). Base retargeted testmain (test was promoted in #1880 then retired) and the branch rebased onto latest main — the PR is no longer stuck on the dead test branch. Direction updated per the 2026-07-21 decision in #1867: the catalog view should be the authenticated home (with persistent nav), not a card on the chat-first home. Scope + TODO below. Tracked as item 1869-r in #1881.

Part of #1867 ("Chat home catalog awareness + in-chat valuation handoff") and #1881 (onboarding v2).

The 2026-07-21 reframe

Original direction (as-built here): add a claimed-catalog card into the chat-first home's greeting CTA slot. The 2026-07-21 decision in #1867 supersedes that framing — the catalog view should be the primary authenticated landing surface, with the persistent nav, rather than a card bolted onto a chat-first home.

The building blocks for that already exist on main:

  • Persistent navcomponents/Sidebar wraps every authenticated route via app/layout.tsx.
  • Catalog viewapp/catalogs (CatalogsPageCatalogsPageContent) already renders a catalog-first surface inside that nav.

So "catalog-is-home" is mostly a landing-surface routing decision (what the authenticated / renders/redirects to), not net-new UI.

What this PR currently contains (transitional foundation, kept non-regressive)

Rather than regress the home back to the circular marketing link while the landing redesign is specced, the rebased commit keeps the catalog-awareness foundation that's correct under either framing:

  • lib/home/getHomeCatalogCardState.ts — pure selector (TDD): claimed catalog → name + trustworthy value band / measured tracks, degrading to name-only, never back to the marketing link.
  • hooks/useHomeCatalogCard.ts — composed from the same provider-backed useCatalogs / useCatalogMeasurements hooks the valuation hero uses (react-query dedupes).
  • components/Home/CatalogCard.tsx, components/Home/HomeCatalogCta.tsx — the card + CTA slot (DESIGN.md: shadow-as-border, achromatic chrome).
  • lib/home/getHomeSuggestedPrompts.ts — the "What's my catalog worth?" chip anchors to the claimed catalog by name, routing the ask into the existing catalog toolset.

This kills the circular recoupable.dev/valuation CTA today; the selector/hook are reused by the catalog-is-home landing.

TODO — catalog-is-home landing (the reframe's remaining scope)

Deferred out of this PR because it changes the core authenticated product surface and needs design sign-off + roster-gated browser verification:

  • Decide the authenticated / behavior for accounts with a claimed catalog: render the catalog view at / (reusing CatalogsPageContent) vs. redirect to /catalogs, keeping the chat reachable. Interacts with HomePage's onboarding-sequence routing and the ?q= initial-message path.
  • Demote the chat-home card framing once the catalog view is the landing surface (the card's selector/hook stay; the greeting-slot placement goes).
  • DESIGN.md pass on the catalog-first landing (nav emphasis, valuation hero placement).
  • Browser verification on a preview.

Verification gate

Full end-to-end verification needs a populated roster/catalog, gated on api item 1b (api#777 — link the searched Spotify artist). The landing-surface change also needs a preview + design review before it merges.

Gates (this rebased revision)

  • pnpm vitest run lib/home — 41 passing (incl. getHomeCatalogCardState, getHomeSuggestedPrompts).
  • Rebased cleanly onto latest main; base retargeted to main.

🤖 Generated with Claude Code

@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@vercel

vercel Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
chat Ready Ready Preview Jul 22, 2026 1:46pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@sweetmantech, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 48 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a4acd86a-cdc4-4eb1-a936-e0982a92a2c2

📥 Commits

Reviewing files that changed from the base of the PR and between d258412 and 7c0695d.

⛔ Files ignored due to path filters (2)
  • lib/home/__tests__/getHomeCatalogCardState.test.ts is excluded by !**/*.test.* and included by lib/**
  • lib/home/__tests__/getHomeSuggestedPrompts.test.ts is excluded by !**/*.test.* and included by lib/**
📒 Files selected for processing (7)
  • components/Chat/ChatGreeting.tsx
  • components/Home/CatalogCard.tsx
  • components/Home/HomeCatalogCta.tsx
  • components/Home/HomeSuggestedPrompts.tsx
  • hooks/useHomeCatalogCard.ts
  • lib/home/getHomeCatalogCardState.ts
  • lib/home/getHomeSuggestedPrompts.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/home-catalog-awareness

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3ea3f78043

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

hasValuation: valuation.show,
hasRuns: tasksState.view === "runs",
artistName: selectedArtist?.name || "",
catalogName: catalogsData?.catalogs?.[0]?.name || "",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use catalog-card valuation when choosing prompts

When an artist is selected but has no artist-scoped measurements, useHomeValuation() returns false while HomeCatalogCta can still render the whole-catalog card with a valuation. Because this component only passes the claimed catalogName while hasValuation remains tied to the hero state, getHomeSuggestedPrompts emits “What's my catalog worth?” even though a valuation is already visible, sending users into a redundant estimate instead of the intended valuation-explanation prompt.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2 issues found across 9 files

Confidence score: 4/5

  • In components/Home/HomeCatalogCta.tsx, the CTA can render (and be clicked) in a pre-load state before useCatalogs() resolves, so claimed-catalog users may be briefly routed toward the wrong marketing flow instead of their catalog experience—gate the CTA behind an explicit catalog-loading state before merging.
  • In components/Home/HomeSuggestedPrompts.tsx, unresolved useCatalogs data can produce a generic seeded prompt while showing the same catalog-worth chip label, which creates subtle intent/label mismatch and inconsistent downstream prompt behavior—defer prompt seeding until catalog data is known (or align label and fallback prompt).
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="components/Home/HomeCatalogCta.tsx">

<violation number="1" location="components/Home/HomeCatalogCta.tsx:17">
P2: Claimed-catalog users briefly see—and can click—the marketing valuation CTA on an uncached initial load before `useCatalogs()` resolves, then it swaps to the catalog card. Represent the catalog-loading state separately and suppress this fallback until the claimed-catalog query has settled.</violation>
</file>

<file name="components/Home/HomeSuggestedPrompts.tsx">

<violation number="1" location="components/Home/HomeSuggestedPrompts.tsx:23">
P3: If `useCatalogs` hasn't resolved, `catalogsData` is undefined and `catalogName` falls back to an empty string; the UI then shows the same chip label "What's my catalog worth?" but seeds a generic prompt rather than a catalog-anchored prompt. This creates a brief label-to-prompt mismatch if a user clicks before the query resolves. Consider delaying the generic prompt branch until after loading/error is known, or change the chip to a loading/disabled state (or an explicit generic label) while `useCatalogs()` is unresolved so the visible label matches the eventual prompt.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

const HomeCatalogCta = () => {
const catalogCard = useHomeCatalogCard();

if (catalogCard.show) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Claimed-catalog users briefly see—and can click—the marketing valuation CTA on an uncached initial load before useCatalogs() resolves, then it swaps to the catalog card. Represent the catalog-loading state separately and suppress this fallback until the claimed-catalog query has settled.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/Home/HomeCatalogCta.tsx, line 17:

<comment>Claimed-catalog users briefly see—and can click—the marketing valuation CTA on an uncached initial load before `useCatalogs()` resolves, then it swaps to the catalog card. Represent the catalog-loading state separately and suppress this fallback until the claimed-catalog query has settled.</comment>

<file context>
@@ -0,0 +1,44 @@
+const HomeCatalogCta = () => {
+  const catalogCard = useHomeCatalogCard();
+
+  if (catalogCard.show) {
+    return (
+      <div className="mb-4 mt-4 text-left text-sm font-normal tracking-normal">
</file context>

const { selectedArtist } = useArtistProvider();
const valuation = useHomeValuation();
const tasksState = useHomeTasksModuleState();
const { data: catalogsData } = useCatalogs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: If useCatalogs hasn't resolved, catalogsData is undefined and catalogName falls back to an empty string; the UI then shows the same chip label "What's my catalog worth?" but seeds a generic prompt rather than a catalog-anchored prompt. This creates a brief label-to-prompt mismatch if a user clicks before the query resolves. Consider delaying the generic prompt branch until after loading/error is known, or change the chip to a loading/disabled state (or an explicit generic label) while useCatalogs() is unresolved so the visible label matches the eventual prompt.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/Home/HomeSuggestedPrompts.tsx, line 23:

<comment>If `useCatalogs` hasn't resolved, `catalogsData` is undefined and `catalogName` falls back to an empty string; the UI then shows the same chip label "What's my catalog worth?" but seeds a generic prompt rather than a catalog-anchored prompt. This creates a brief label-to-prompt mismatch if a user clicks before the query resolves. Consider delaying the generic prompt branch until after loading/error is known, or change the chip to a loading/disabled state (or an explicit generic label) while `useCatalogs()` is unresolved so the visible label matches the eventual prompt.</comment>

<file context>
@@ -19,11 +20,13 @@ const HomeSuggestedPrompts = () => {
   const { selectedArtist } = useArtistProvider();
   const valuation = useHomeValuation();
   const tasksState = useHomeTasksModuleState();
+  const { data: catalogsData } = useCatalogs();
 
   const prompts = getHomeSuggestedPrompts({
</file context>

Chat home for an account that just claimed a catalog said "Ask me about
your roster" and linked back to recoupable.dev/valuation - the funnel the
signup had completed 60 seconds earlier - with no awareness of the claimed
catalog (verified prod 2026-07-20, #1867).

(a) Home catalog awareness: when the account has >=1 claimed catalog, the
greeting's CTA slot renders a catalog card (name, est. value band + tracks
measured when the whole-catalog measurements read is trustworthy) linking
to /catalogs/{id}, replacing the circular marketing link. No claimed
catalog keeps the current valuation-funnel link, and the chat#1850
valuation hero branch is untouched.

(b) In-chat handoff (pragmatic v1): the "What's my catalog worth?"
suggested prompt now anchors to the claimed catalog by name and directs
the model to start from the songs already in the Recoup catalog, so the
ask routes to the existing catalog toolset (select_catalog_songs via the
recoup-api MCP) instead of dead-ending on a generic estimate. Free-text
routing lives in the api-side system prompt and is out of scope here.

New: getHomeCatalogCardState selector (TDD), useHomeCatalogCard composed
hook, CatalogCard + HomeCatalogCta components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sweetmantech
sweetmantech force-pushed the feat/home-catalog-awareness branch from 3ea3f78 to 7c0695d Compare July 22, 2026 13:41
@sweetmantech
sweetmantech changed the base branch from test to main July 22, 2026 13:41
@sweetmantech sweetmantech changed the title feat(home): claimed-catalog card + catalog-anchored valuation prompt (chat#1867) feat(home): catalog awareness on the authenticated home — reframe toward catalog-is-home (chat#1867/#1881 item 1869-r) Jul 22, 2026
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