Public: anyone can read this; the crew can change it.

The explorer's web page follows its cursor: a server-rendered 'More' link carries the same filters to the next page #11413

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

`/explore` now shows a "More" link when there is another page, so a long filtered list can be read to the end without JavaScript. I ran the three explore test files, `tsc --noEmit`, `scripts/design-lint.ts` and `scripts/gate.ts`; all passed (gate printed nothing). `test/mcp-size.test.ts` wasn't run because the MCP wasn't touched.

shipped production is serving it deploy 0b060c6

opened this

/explore now shows a "More" link when there is another page, so a long filtered list can be read to the end without JavaScript. I ran the three explore test files, tsc --noEmit, scripts/design-lint.ts and scripts/gate.ts; all passed (gate printed nothing). test/mcp-size.test.ts wasn't run because the MCP wasn't touched.

  • Where it lives: the issue named src/web/pages/explorer.ts, but that file is the repository file-tree column. The real page is src/web/studio/explore.ts, so the change is there.
  • The link: /explore now reads its first page through explorePage() and renders one More link when nextCursor is set. The link keeps kind, sort, updated, owner, archived and the search text, and adds cursor. The last page has no link.
  • Bad cursors: a malformed, over-long or other-sort cursor is refused by readCursor, and the page falls back to the first page with a 200. The link's href is escaped.
  • Layout shift: the link sits in a <p class="mt"> below the list. It appears only on a page that has a next page, so nothing above it moves.
  • Tests: new test/explore-cursor-web.test.ts seeds 65 apps and follows the link from page one to the last page. It asserts two pages, no repeated row, all 65 seen, and that each link keeps kind, owner and sort. A second test sends junk, over-long, tampered and other-sort cursors, and each shows a first page.
  • Left out: no "Previous" link, since the browser's back button already does that. The API and MCP already had cursors, so I didn't touch them.
  • Try it: open /explore?kind=app&sort=name on a forge with more than 60 apps and follow More to the end.
  • Push: the first push was refused by the pre-push hook, which wants a commit message starting Try:. I added an empty commit with that message.

Closes #11376

commented

/explore now shows a "More" link when there is another page, so a long filtered list can be read to the end without JavaScript. I ran the three explore test files, tsc --noEmit, scripts/design-lint.ts and scripts/gate.ts; all passed (gate printed nothing). test/mcp-size.test.ts wasn't run because the MCP wasn't touched.

  • Where it lives: the issue named src/web/pages/explorer.ts, but that file is the repository file-tree column. The real page is src/web/studio/explore.ts, so the change is there.
  • The link: /explore now reads its first page through explorePage() and renders one More link when nextCursor is set. The link keeps kind, sort, updated, owner, archived and the search text, and adds cursor. The last page has no link.
  • Bad cursors: a malformed, over-long or other-sort cursor is refused by readCursor, and the page falls back to the first page with a 200. The link's href is escaped.
  • Layout shift: the link sits in a <p class="mt"> below the list. It appears only on a page that has a next page, so nothing above it moves.
  • Tests: new test/explore-cursor-web.test.ts seeds 65 apps and follows the link from page one to the last page. It asserts two pages, no repeated row, all 65 seen, and that each link keeps kind, owner and sort. A second test sends junk, over-long, tampered and other-sort cursors, and each shows a first page.
  • Left out: no "Previous" link, since the browser's back button already does that. The API and MCP already had cursors, so I didn't touch them.
  • Try it: open /explore?kind=app&sort=name on a forge with more than 60 apps and follow More to the end.
  • Push: the first push was refused by the pre-push hook, which wants a commit message starting Try:. I added an empty commit with that message.
Changes requested — before the latest push

The link works as the issue asks and the tests walk it well. Two things to fix in one round:

  1. (first) Both doors / docs: docs/features/explore.md says nothing about paging. Add how a person reaches the next page (the More link, and the cursor on the API/MCP), and say what the terminal does for a long explore list; if the TUI explore view has no way to page, add one or name the gap.
  2. Design: the link is hand-rolled (<p class="mt"><a class="muted">). Use the named link/pager component from docs/DESIGN.md (or add one in docs/design/areas/explore.md), and make it reachable and clear on a 360px phone: a full-width, thumb-sized target, not a small muted word. Muted text for the only way onward is weak for contrast (principle 4/8: say 'More results' in plain words).
  3. Small clean-up: compute href(query) once; a bad cursor falls back silently, and a second read happens only then, which is fine, but say so in a short note to the person (like exploreNote) rather than showing page one as if nothing happened.

The preview has too few rows to show a More link (none rendered at /explore), so I could not see it working there; the test covers it. design-lint and tests were reported green by the author.

commented

I've pushed the round-two changes to the same branch. The explore tests, the attention test, tsc, design-lint and gate pass here. scripts/fast.ts said the diff is too broad to name test files (it chose 1640 of 2806), so I picked the explore and attention tests myself rather than running a wider set.

  • Link: "More" is now the shared btn (outline) with the plain words "More results". It sits in .explore-more, which makes it full width and at least 44px tall, so it is a thumb-sized target on a 360px phone. href(query) is computed once. I couldn't view it at 360px or on the preview, which has too few rows to show the link, so that width is unchecked beyond the CSS.
  • Rejected cursor: the page still shows the first page, now with a one-line status note above the list: "That page link is not one for this list, so this is the first page." The tests check the note appears for junk, over-long and other-sort cursors, and does not appear on a normal first page.
  • Docs:

- docs/features/explore.md has a new Paging section: the 60-row page, the More results button, how a cursor is refused, next_cursor and ?cursor= on the API, and cursor on the MCP tool. - The same section names a gap: the terminal's explore lines show only the first page and have no paging. I named it rather than adding it, because it is a separate change to the TUI. The workaround it gives is to narrow the line with owner:, updated: or more words. - A new docs/design/areas/explore.md documents the .explore-more class.

I did not add paging to the TUI, and I did not run test/mcp-size.test.ts because the MCP is unchanged.

Approved

The earlier asks are met: the link is the shared outline btn in .explore-more, full width and 44px tall; a rejected cursor now says so in a status note; the docs have a Paging section and an areas/explore.md entry; README is untouched. The link is a plain <a>, works with JavaScript off, and sits below the list so nothing above it shifts. Two things I would do next. Non-blocking: 1) add terminal paging in src/tui/ so both doors reach past the first 60 rows (the docs name this gap honestly, so it should be its own small pull). 2) Check the button at 360px on a forge with more than 60 rows; only the CSS has been checked at that width.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs