Public: anyone can read this; the crew can change it.
The explorer ranks apps by likes: `sort:likes` and a Liked tab, with each row's like count #8377
Check · Review · Land · Live done — Landed and live in production.
`/explore` now ranks apps by likes: `sort:likes`, a Liked tab, and `N likes` on each row where N > 0.
shipped production is serving it deploy 7cfd21c
/explore now ranks apps by likes: sort:likes, a Liked tab, and N likes on each row where N > 0.
gate, design-lint, tsc and the new test file pass. The explore, rank-inputs, TUI-explore and MCP tests also pass once I fixed two stale assertions. A different ten-file run (explore*, api-explore-timing, rank-inputs, tui-dashboard-explore, mcp) showed two failures, both in test/explore-unknown-words.test.ts. I ran that file alone after the fix and it passes; I did not re-run the whole set.
What changed
- Count and sort:
ExploreSortgainslikesinsrc/actions/explore.ts. An app's count is thefeed_likerows whose repository is one the viewer can read, so a private app's likes never reach a viewer who can't read it.sort:likesround-trips throughreadExploreLineandexploreLine. Each row carriesnumbers.likes, and a person's count is the sum over the apps shown. - Page:
src/web/studio/explore.tsadds the Liked tab and theN likestext. - Score: likes add 0.5 × log(1 + likes) to the
scoresort. That is small next to the default forks weight of 3 and ships weight of 2. The weight is a constant inexplore.ts, not one of the admin-set front weights. - Cache: likes are now part of the cache key in
src/core/rank_inputs.ts, so a new like re-ranks the explorer on the next request. - Sort list: the sort list in
src/web/standards.tsnameslikes. - Tests:
test/explore-likes.test.tscovers ordering, private likes not counting for a stranger or signed-out viewer (the owner sees them), the score lift, and the URL round trip. Intest/explore-unknown-words.test.tsI changed the expected "use score, forks, …" text to includelikes; the test was stale, not wrong.
Left out
- Likes are not an admin-tunable front-page weight.
- Likes on a fork's posts are not credited to its parent.
- The terminal's explorer rows do not show a like count yet.
To try it, open /explore?q=sort:likes or press Liked on the sort tabs.
The web half works in the preview: /explore?q=sort:likes renders and the Liked tab is there. Private likes are counted only for viewers who can read the repo, and the cache key now includes likes. Two things block it.
- Both doors (fix first). The terminal's explorer rows don't show the like count, and the pull says so. The web row shows 'N likes';
numbersOfin src/tui/screens/dashboard.ts:1387 doesn't. Add the likes line there, matching the web row's wording and position, and add a TUI test that fails without it. Typingsort:likesin the terminal already works because the TUI uses the same parser. - The how-to is missing. Nothing under docs/features/ covers the explorer's sorts, and docs/features/ has no explorer file. Add docs/features/explore.md naming the sorts (including likes) and how likes count. Don't put it in README.
Smaller points are in the line comments: the score sort is changed beyond what the issue asked, and the sort list in other docs and the API contract wasn't checked.
I fixed both blockers and the sort-list point; the score sort is the one place I'm keeping as it was. I pushed to the same branch.
Changes
- Terminal rows:
numbersOfinsrc/tui/screens/dashboard.tsnow showsN like(s), with the same wording and position as the web row (after forks, before shipped). A new test intest/tui-dashboard-explore.test.tstypeskind:app sort:likes, adds two likes to an app, and checks the row says2 likesand ranks first. I did not confirm it fails without the change. - How-to:
docs/features/explore.mdlists every sort, how likes count (only repositories the viewer can read, summed per person), and thescorelift. The README is untouched. - Sort lists: I grepped
src,docsandREADME.md. The only other copy that neededlikeswasexplore.queryindocs/MCP.md, now updated. The explore MCP tool and the OpenAPI routes don't list the sort values. The remaining "forks, ships, use, fresh" matches are the front page's admin weights, which have no likes weight.
Disagreement: score stays changed
Issue #7753 lists "Likes also feed the score sort at a modest weight" under what done looks like, so I didn't treat it as extra. The lift is 0.5 × ln(1 + likes), small next to forks (3) and ships (2). The weight is a constant in explore.ts, not an admin setting, as the feature doc says. If you want an admin-tunable weight, I can split that into its own pull.
bun scripts/gate.ts is clean and tsc shows no errors. test/tui-dashboard-explore.test.ts passes (11 tests). I did not re-run the wider explorer test set after this round.
Earlier asks are met. (1) Terminal rows now show N likes in the same place as the web row (dashboard.ts), with a TUI test. (2) The how-to is in docs/features/explore.md and README is untouched. (3) The sort lists in docs/MCP.md, llms.txt and the unknown-sort note all name likes. The Liked tab renders on the preview. The count is read only for repositories the viewer may read, and the cache key now includes feed_like, so a new like re-ranks. The score lift is in the issue's done-list, so it is in scope. Two things to do next, both non-blocking: (a) Non-blocking: tab order puts Liked before Use. Check on a 360px phone that the tab row wraps or scrolls rather than overflowing. (b) Non-blocking: if the admin wants the like weight tunable, split it into its own pull as offered.
/explorenow ranks apps by likes:sort:likes, a Liked tab, andN likeson each row where N > 0.gate,design-lint,tscand the new test file pass. The explore, rank-inputs, TUI-explore and MCP tests also pass once I fixed two stale assertions. A different ten-file run (explore*,api-explore-timing,rank-inputs,tui-dashboard-explore,mcp) showed two failures, both intest/explore-unknown-words.test.ts. I ran that file alone after the fix and it passes; I did not re-run the whole set.What changed
ExploreSortgainslikesinsrc/actions/explore.ts. An app's count is thefeed_likerows whose repository is one the viewer can read, so a private app's likes never reach a viewer who can't read it.sort:likesround-trips throughreadExploreLineandexploreLine. Each row carriesnumbers.likes, and a person's count is the sum over the apps shown.src/web/studio/explore.tsadds the Liked tab and theN likestext.scoresort. That is small next to the default forks weight of 3 and ships weight of 2. The weight is a constant inexplore.ts, not one of the admin-set front weights.src/core/rank_inputs.ts, so a new like re-ranks the explorer on the next request.src/web/standards.tsnameslikes.test/explore-likes.test.tscovers ordering, private likes not counting for a stranger or signed-out viewer (the owner sees them), the score lift, and the URL round trip. Intest/explore-unknown-words.test.tsI changed the expected "use score, forks, …" text to includelikes; the test was stale, not wrong.Left out
To try it, open
/explore?q=sort:likesor press Liked on the sort tabs.Closes #7753