Skip to content

feat(feed): surface recommended playlists inside the For You feed#14411

Open
dylanjeffers wants to merge 2 commits into
mainfrom
feat/for-you-collections
Open

feat(feed): surface recommended playlists inside the For You feed#14411
dylanjeffers wants to merge 2 commits into
mainfrom
feat/for-you-collections

Conversation

@dylanjeffers
Copy link
Copy Markdown
Contributor

Summary

The For You feed (web + mobile) currently renders tracks only — a documented limitation introduced when the lineup migrated to TanStack Query. This brings collections back, scoped to a single "Playlists for you" strip inlined into the lineup.

Approach

`TrackLineup` (web + mobile) already accepts a `delineatorMap: Record<index, ReactElement>` extension point. Feeding it a strip at position 5 surfaces recommended playlists inline without rewriting the lineup or touching playback semantics:

  • New hook `useTrendingPlaylists` (mirror of `useTrendingAlbums`, `type: 'playlist'`) — there is no per-user recommended-collections endpoint in either the Go API or discovery-provider, so trending playlists is the closest stable signal available right now.
  • New `ForYouCollectionsRow` component on web (shared by desktop + mobile-web) and a native equivalent using `CollectionList horizontal`.
  • `FeedPageContent` (desktop + mobile-web) and `FeedScreen` (native) pass `delineatorMap: { 5: }` when the For You tab is active.

Scope note

When the proper inline-mixed lineup ships — i.e. `useForYouFeed` returning mixed track + collection IDs and `TrackLineup` rendering `CollectionTile` for the collection branch — this strip can go away. That's a larger change (lineup + playback queue semantics) deferred to a follow-up.

Test plan

  • Open the Feed page on web and switch to For You. After scrolling past the first ~5 tracks, the "Playlists for you" strip appears inline with horizontal-scrolling `CollectionCard`s.
  • Switch to Following — the strip does NOT appear.
  • Repeat on mobile-web (responsive) and native iOS / Android.
  • Confirm the strip renders `null` (no flash) when the trending-playlists query is pending or empty.

🤖 Generated with Claude Code

The For You feed (web + mobile) currently renders tracks only — a
documented limitation introduced when the lineup migrated to
TanStack Query. Collections never made it back. This adds them.

Approach: TrackLineup already exposes a `delineatorMap` extension
point (Record<index, ReactElement>). Feeding it a single
"Playlists for you" strip at position 5 inlines a horizontal scroll
of recommended playlists into the lineup without rewriting the
lineup itself or touching playback semantics. When the proper
inline-mixed lineup ships (Track + Collection tiles ordered by the
backend's For You scoring), this strip can go away.

Data source: `useTrendingPlaylists` (new), mirroring
`useTrendingAlbums` with `type: 'playlist'` against
`sdk.playlists.getTrendingPlaylists`. There is no per-user
recommended-collections endpoint in either the Go API
(packages/identity aside, only `v1_users_recommended_tracks.go`
exists for personalization) or discovery-provider, so trending
playlists is the closest stable signal available right now.

- packages/common/src/api/tan-query/collection/useTrendingPlaylists.ts: new hook
- packages/common/src/api/tan-query/queryKeys.ts: trendingPlaylists key
- packages/common/src/api/index.ts: re-export
- packages/web/src/pages/feed-page/components/ForYouCollectionsRow.tsx: new strip (shared by desktop + mobile-web)
- packages/web/src/pages/feed-page/components/{desktop,mobile}/FeedPageContent.tsx: pass delineatorMap on For You
- packages/mobile/src/screens/feed-screen/ForYouCollectionsRow.tsx: native equivalent using CollectionList horizontal
- packages/mobile/src/screens/feed-screen/FeedScreen.tsx: pass delineatorMap on For You

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 27, 2026

⚠️ No Changeset found

Latest commit: 6b5b314

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

End-to-end validation against prod (2026-05-27) showed
/v1/playlists/trending returns an empty data array whenever
user_id is set — confirmed for both type=playlist and type=album
across week/month/year/allTime. Without user_id the same endpoint
returns the expected 10 playlists.

The hook was passing OptionalId.parse(currentUserId), so the
"Playlists for you" strip would silently render nothing for every
logged-in user (i.e. the only audience the For You feed targets).

Drop user_id from the call. has_current_user_reposted /
has_current_user_saved on each playlist payload will be false
under this code path until the backend regression is fixed —
acceptable for the discovery strip, where the cards link out and
the badges aren't currently shown on the card surface.

Same bug affects the pre-existing useTrendingAlbums hook (which
this hook mirrored). Filed separately — see PR description.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dylanjeffers
Copy link
Copy Markdown
Contributor Author

End-to-end validation against prod (2026-05-27) — partial issue found and fixed inline, plus one backend regression flagged for follow-up.

What I checked

  1. Hook impl (packages/common/src/api/tan-query/collection/useTrendingPlaylists.ts) — calls `sdk.playlists.getTrendingPlaylists({ time, limit, type: 'playlist' })`, which hits `GET /v1/playlists/trending` ✓
  2. TrackLineup wiring — `delineatorMap?.[index] ? delineatorMap[index] : null` at `packages/web/src/components/lineup/TrackLineup.tsx:439` renders any React element as-is, no track-type coupling ✓
  3. Endpoint behavior on prod:
call result
`GET /v1/playlists/trending?limit=10` 10 playlists
`GET /v1/playlists/trending?limit=10&user_id=Nzk3QE0` (dylan_audius) 0
`GET /v1/playlists/trending?limit=10&user_id=oaM5J` (g4bba) 0
`GET /v1/playlists/trending?limit=10&user_id=…&type=album` 0
`GET /v1/playlists/trending?limit=10&user_id=…&time=allTime` 0

The bug I introduced

The original hook mirrored `useTrendingAlbums` exactly, including `userId: OptionalId.parse(currentUserId)`. Because the trending-playlists endpoint returns `[]` for any `user_id`, the "Playlists for you" strip would silently never render for a logged-in user — the only audience For You targets.

Fix in this push (`6b5b314968`)

Drop `user_id` from the hook's SDK call. Without it the endpoint returns 10 playlists as expected. The trade-off is that `has_current_user_reposted` / `has_current_user_saved` flags come back as `false` — fine for the discovery strip where the cards just link out and don't show those badges.

Pre-existing bug surfaced

`useTrendingAlbums` (the hook this one mirrored, used on Explore) has the same problem: it also passes `user_id` and so would also return 0 albums when logged in. I haven't touched that here — separate scope, separate PR.

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant