Skip to content

feat: show reader picks in the left rail - #77

Merged
dimslaev merged 2 commits into
masterfrom
feat/rail-reader-picks
Oct 10, 2026
Merged

dimslaev merged 2 commits into
masterfrom
feat/rail-reader-picks

Conversation

@dimslaev

Copy link
Copy Markdown
Owner

What

  • New left-rail panel Reader picks (after Topic map, meta "last 30 days"): the articles readers liked most in the last 30 days, top 6 with like_count > 0.
  • Each row shows the agent's score as a MiniRail, a mono "PUBLISHER · OCT 4" meta line, the title (13px, new tab, articleClickHandlers with surface: "reader_picks"), and the existing LikeButton with its count.
  • Data: readArticles({ sort: "likes-desc", since: 30 days ago, limit: 20 }), key ["articles", "reader-picks"], staleTime 5 min. No backend change.
  • No rows: the panel returns null and RailPanel hides it.
  • docs/product.md: one line in the rails paragraph.

Changes from the plan

  • Fixed liking, which is broken on master. WhoWrote (feat: show who wrote the wire in the left rail #74) keeps its origin counts under ["articles", "origins", …]. That data has no data array, so LikeButton's optimistic patchArticle threw Cannot read properties of undefined (reading 'map') in onMutate. The PUT was never sent and the reader got a "Something went wrong" toast. This hit the feed's like button too, not only the panel. likes.spec didn't catch it because it only checks the optimistic count, which goes back to its old value after an error. The fix is a guard in patchArticle (if (!data?.data) return data). I picked this over moving WhoWrote's key so any future non-list ["articles", …] query is covered too. The plan relies on that patch reaching every ["articles", …] query, which is why I fixed it here.
  • The meta line is uppercase, as in the design image and the feed's ArticleRow (the plan didn't say either way).

Verified

  • bun run lint (biome) is clean on the changed files. bun run build (tsc + vite) passes.
  • Full Playwright suite on the merged tree, run locally against a real backend: 41 passed, 1 failed.
    • The one failure is likes.spec.ts:75 ("Password" tab). It fails the same way on unmodified master: the profile page has no Password tab any more. It has nothing to do with this PR.
  • tests/reader-picks.spec.ts, all passing:
    • mocked likes-desc response with 3 liked and 2 unliked rows: 3 rows, in like order, counts 5/3/1, link opens in a new tab, meta shows publisher and date
    • all counts 0: the panel is hidden
    • signed in, real backend: a like in the feed shows up in the panel with the same count, and an unlike in the panel lowers the feed count. The test restores the article afterwards. It uses feed row 3 so it doesn't race likes.spec, which toggles row 1.
    • logged out: liking in the panel redirects to /login
  • How I ran it: Postgres 16 + pgvector on the host (the ghcr.io db image pull was blocked by the network policy), prestart.sh seed data, fastapi dev, mailcatcher in Docker for auth.setup.ts. The browser was pointed at the pre-installed Chromium through an uncommitted local config.
  • Checked visually: a screenshot of the panel with 4 liked seed articles, compared against the picker's "Reader picks" image.
  • Merged latest master, which includes stories feat: add agent-named stories to the right rail #76. The only conflict was the imports in panels.tsx. RIGHT is kept as master has it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NjivDE4oKNKuycRKAPiTfQ


Generated by Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NjivDE4oKNKuycRKAPiTfQ
# Conflicts:
#	frontend/src/components/Rails/panels.tsx
@dimslaev
dimslaev merged commit 14cfec1 into master Oct 10, 2026
3 of 5 checks passed
@dimslaev
dimslaev deleted the feat/rail-reader-picks branch October 10, 2026 10:40
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