feat(onboarding): add artists by Spotify typeahead, not free text (chat#1889 row 8)#1892
feat(onboarding): add artists by Spotify typeahead, not free text (chat#1889 row 8)#1892sweetmantech wants to merge 1 commit into
Conversation
chat#1889 matrix row 8 — the highest-value item after convergence. AddArtistForm took a free-text name and useAddRosterArtist posted only that, so an added artist had no Spotify id. Without one there is no catalog and no valuation, which makes the payoff structurally unreachable — and that is the only forward path for the cold-start cohort: of the 9 accounts that received a welcome email 2026-07-23..25, 6 had zero artists and had never run a valuation. - AddArtistForm uses the existing SpotifyArtistSearch typeahead (same component verify-socials adopted in #1882), so a pick resolves to a real Spotify id. - useAddRosterArtist attaches the profile URL (via buildSocialFixPayload) and the Spotify avatar through PATCH /api/artists/{id} after creation, since POST /api/artists accepts only a name. Enrichment failure is non-fatal. - ConfirmRosterStep no longer tells an empty roster we set it up "from your valuation" — false for two thirds of signups. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
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. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 37 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a332e38fe7
ℹ️ 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".
| const added = await addArtist(artist.name, { | ||
| profileUrl: artist.external_urls.spotify, | ||
| image: artist.images?.[0]?.url, | ||
| }); |
There was a problem hiding this comment.
Seed a valuation from the selected Spotify artist
For a cold-start account with no catalogs, this selection passes only the artist name, profile URL, and image, discarding artist.id; the hook then performs only the artist POST/PATCH. Unlike hooks/useAddSpotifyArtist.ts, it never calls runValuation(accessToken, artist.id), so /setup/catalog can still redirect these users to a catalogs page that says "No catalogs found" despite the new copy promising that adding the artist gets the catalog valued.
Useful? React with 👍 / 👎.
| await saveArtist(accessToken, artist.account_id, { | ||
| ...(payload ? { profileUrls: payload.profileUrls } : {}), | ||
| ...(options.image ? { image: options.image } : {}), | ||
| }); |
There was a problem hiding this comment.
Treat post-create enrichment failures as successful adds
When the initial artist POST succeeds but this PATCH fails (for example, during a transient API/network error), control reaches the outer catch, skips getArtists(), and returns false. The form therefore remains open and invites the user to select the artist again, issuing another POST and potentially creating duplicate roster entries even though the first artist already exists; isolate enrichment failure from creation and still refresh/close after a successful create.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
2 issues found across 4 files
Confidence score: 2/5
- In
components/Onboarding/AddArtistForm.tsx, adding the first artist from an empty roster can skip triggering catalog valuation, so users may move forward without the valuation step the flow now promises — trigger valuation from the known selectedartist.idwhen the first artist is added. - In
hooks/onboarding/useAddRosterArtist.ts, a temporary PATCH/enrichment failure is surfaced as a full add failure even aftercreateRosterArtisthas already succeeded, which can leave the form open and cause duplicate artists on retry — separate enrichment error handling from create success and treat partial success explicitly.
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="hooks/onboarding/useAddRosterArtist.ts">
<violation number="1" location="hooks/onboarding/useAddRosterArtist.ts:57">
P1: A transient PATCH failure makes the form report the add as failed even though `createRosterArtist` already persisted the artist. The form remains open and a retry can create a duplicate; catch enrichment errors separately, notify the user if appropriate, then refresh and return success.</violation>
</file>
<file name="components/Onboarding/AddArtistForm.tsx">
<violation number="1" location="components/Onboarding/AddArtistForm.tsx:24">
P1: Adding the first artist from an empty onboarding roster still never starts catalog valuation, so users can continue past this step without the catalog the new copy promises. This handler has the selected `artist.id`; route it through `useAddSpotifyArtist` (or trigger the same first-roster valuation flow here) rather than the name/profile-only hook.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| if (artist?.account_id && (payload || options.image)) { | ||
| await saveArtist(accessToken, artist.account_id, { | ||
| ...(payload ? { profileUrls: payload.profileUrls } : {}), | ||
| ...(options.image ? { image: options.image } : {}), | ||
| }); | ||
| } |
There was a problem hiding this comment.
P1: A transient PATCH failure makes the form report the add as failed even though createRosterArtist already persisted the artist. The form remains open and a retry can create a duplicate; catch enrichment errors separately, notify the user if appropriate, then refresh and return success.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At hooks/onboarding/useAddRosterArtist.ts, line 57:
<comment>A transient PATCH failure makes the form report the add as failed even though `createRosterArtist` already persisted the artist. The form remains open and a retry can create a duplicate; catch enrichment errors separately, notify the user if appropriate, then refresh and return success.</comment>
<file context>
@@ -27,7 +45,22 @@ export function useAddRosterArtist() {
+ const payload = options.profileUrl
+ ? buildSocialFixPayload(options.profileUrl)
+ : null;
+ if (artist?.account_id && (payload || options.image)) {
+ await saveArtist(accessToken, artist.account_id, {
+ ...(payload ? { profileUrls: payload.profileUrls } : {}),
</file context>
| if (artist?.account_id && (payload || options.image)) { | |
| await saveArtist(accessToken, artist.account_id, { | |
| ...(payload ? { profileUrls: payload.profileUrls } : {}), | |
| ...(options.image ? { image: options.image } : {}), | |
| }); | |
| } | |
| if (artist?.account_id && (payload || options.image)) { | |
| try { | |
| await saveArtist(accessToken, artist.account_id, { | |
| ...(payload ? { profileUrls: payload.profileUrls } : {}), | |
| ...(options.image ? { image: options.image } : {}), | |
| }); | |
| } catch { | |
| toast.error("Artist added, but Spotify details could not be saved"); | |
| } | |
| } |
| setIsOpen(false); | ||
| } | ||
| const handleSelect = async (artist: SpotifyArtistSearchResult) => { | ||
| const added = await addArtist(artist.name, { |
There was a problem hiding this comment.
P1: Adding the first artist from an empty onboarding roster still never starts catalog valuation, so users can continue past this step without the catalog the new copy promises. This handler has the selected artist.id; route it through useAddSpotifyArtist (or trigger the same first-roster valuation flow here) rather than the name/profile-only hook.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/Onboarding/AddArtistForm.tsx, line 24:
<comment>Adding the first artist from an empty onboarding roster still never starts catalog valuation, so users can continue past this step without the catalog the new copy promises. This handler has the selected `artist.id`; route it through `useAddSpotifyArtist` (or trigger the same first-roster valuation flow here) rather than the name/profile-only hook.</comment>
<file context>
@@ -1,24 +1,31 @@
- setIsOpen(false);
- }
+ const handleSelect = async (artist: SpotifyArtistSearchResult) => {
+ const added = await addArtist(artist.name, {
+ profileUrl: artist.external_urls.spotify,
+ image: artist.images?.[0]?.url,
</file context>
Matrix row 8 in chat#1889 — the highest-value item after the convergence chain. Independent of #1890/#1891 (different files), so it can be reviewed in parallel.
Why: the payoff was structurally unreachable for most signups
Live cohort from
email_send_log, 2026-07-23 → 2026-07-26:The welcome email fires on account creation regardless of whether a valuation preceded it, so two-thirds of the cohort are cold-start signups. Their only forward path is
AddArtistForm— which took a free-text name and posted only{ name }. No Spotify id → no catalog → no valuation. The number those users were emailed about could never exist.What changed
AddArtistFormusesSpotifyArtistSearch— the same typeahead verify-socials adopted in feat(onboarding): Spotify typeahead in verify-socials (item 3b of #1881) #1882 — so a pick resolves to a real Spotify id, profile URL, and avatar.useAddRosterArtistnow takes{ profileUrl, image }and attaches them via the existingPATCH /api/artists/{id}path after creation, becausePOST /api/artistsaccepts onlyname/account_id/organization_id. ReusesbuildSocialFixPayloadfor the platform detection rather than hand-rolling the shape. Enrichment failure is deliberately non-fatal — the artist is already on the roster and socials can still be fixed in the next step.ConfirmRosterStepcopy: an empty roster was told "We set these artists up from your valuation" — false for 6 of 9 signups. It now reads as an instruction to search, and the empty state names the reward.No api change needed, so no docs/contract change either — this rides two existing endpoints.
Verification
TDD, red → green:
```
RED — free-text field still present, no typeahead
Test Files 1 failed (1)
Tests 2 failed (2)
GREEN
pnpm exec vitest run components/Onboarding lib/onboarding
Test Files 18 passed (18)
Tests 70 passed (70)
```
The new test asserts the free-text
Artist namefield is gone, the Spotify searchbox is present, and picking a result callsaddArtistwith the resolved profile URL + avatar.pnpm exec tsc --noEmitclean for the touched files. Preview click-through pending (needs an authed empty-roster account).Tracked in chat#1889 (matrix row 8).
Summary by cubic
Replace free-text artist input with Spotify typeahead in onboarding so added artists have a real Spotify id, profile URL, and avatar. This lets cold-start signups proceed to catalog and valuation (chat#1889, row 8).
AddArtistFormnow usesSpotifyArtistSearch; selection callsaddArtist(name, { profileUrl, image }).useAddRosterArtistenriches the created artist viaPATCH /api/artists/{id}usingbuildSocialFixPayload; enrichment is non-fatal and the roster refreshes.ConfirmRosterStepcopy to prompt Spotify search for empty rosters and set expectations for the next step.Written for commit a332e38. Summary will update on new commits.