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

Explore has an Atom feed: /explore.atom lists the apps rising and newly made, and the page advertises it #11044

Merged opened this

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

Merged

`GET /explore.atom` now answers Atom, and `/explore` advertises it with a `<link rel="alternate" type="application/atom+xml">`.

shipped production is serving it deploy a985b29

opened this

GET /explore.atom now answers Atom, and /explore advertises it with a <link rel="alternate" type="application/atom+xml">.

The new test file, test/explore-atom.test.ts, passes. bun x tsc --noEmit, scripts/gate.ts, scripts/design-lint.ts, and the existing feed and explore tests are clean. I didn't run the 50 ms budget as its own test. The test only asserts the response is under 500 ms and carries a Server-Timing header.

  • What's in it: the list is read through explore(), the same function the page uses, as a stranger with the page's default ranking. Private apps and archived apps therefore can't appear, and the test creates one of each to prove it.
  • Entries: at most 30, ordered newest-made first. Each links its app page and has a plain-words summary, which is the app's description plus its non-zero fork, like and shipped-this-month counts.
  • Escaping: it uses xml() from src/web/feeds.ts. A test covers <&" directly, and the feed test checks that a description containing & < > " is escaped in the output.
  • Wiring: the route is in src/http/server.ts, and I reserved explore.atom in src/core/reserved.ts so it can't be taken as an account name.
  • Caching: the feed has an ETag and a 5-minute public cache.

Left out:

  • The feed ignores the page's ?q= filters and is always the default ranking.
  • It takes the top-ranked apps and then orders them by creation date. The explore row has no creation date of its own, so it reads dates through repoDatesFor.

Try it: open /explore.atom, or look for the feed link in the head of /explore.

The pre-push hook refused the push until a commit message carried a Try: line, so the commit has one.

Closes #10967

commented

GET /explore.atom now answers Atom, and /explore advertises it with a <link rel="alternate" type="application/atom+xml">.

The new test file, test/explore-atom.test.ts, passes. bun x tsc --noEmit, scripts/gate.ts, scripts/design-lint.ts, and the existing feed and explore tests are clean. I didn't run the 50 ms budget as its own test. The test only asserts the response is under 500 ms and carries a Server-Timing header.

  • What's in it: the list is read through explore(), the same function the page uses, as a stranger with the page's default ranking. Private apps and archived apps therefore can't appear, and the test creates one of each to prove it.
  • Entries: at most 30, ordered newest-made first. Each links its app page and has a plain-words summary, which is the app's description plus its non-zero fork, like and shipped-this-month counts.
  • Escaping: it uses xml() from src/web/feeds.ts. A test covers <&" directly, and the feed test checks that a description containing & < > " is escaped in the output.
  • Wiring: the route is in src/http/server.ts, and I reserved explore.atom in src/core/reserved.ts so it can't be taken as an account name.
  • Caching: the feed has an ETag and a 5-minute public cache.

Left out:

  • The feed ignores the page's ?q= filters and is always the default ranking.
  • It takes the top-ranked apps and then orders them by creation date. The explore row has no creation date of its own, so it reads dates through repoDatesFor.

Try it: open /explore.atom, or look for the feed link in the head of /explore.

The pre-push hook refused the push until a commit message carried a Try: line, so the commit has one.

commented

/explore.atom is now listed as a feed rather than a page in the two tests that failed. The two tests named in the check now pass locally, along with the rest of those two files (9 tests). I did not run tsc, the gate or the full suite.

The Atom feed added in this pull is a new top-level route, and both tests list every top-level route as a page unless it is named as a non-page:

  • test/design-audit.test.ts: I added explore.atom to the not-a-page pattern, next to changelog.atom. This stops it needing an entry in docs/design/audit.md.
  • test/forge-looks.test.ts: I added "/explore.atom": "Atom feed of /explore" to the not-a-page list. This stops it needing a place in app.looks in forge.json.

The tests were wrong, not the code: the feed is not a page, as with /changelog.atom. I pushed the change; the forge's check will now run against it.

Changes requested — before the latest push

The feed works in the preview (valid Atom, Server-Timing present, entries link app pages, private/archived excluded by test). Two things to fix in one round:

  1. Both doors: the terminal has no way to reach the feed and there is no how-to. Add docs/features/explore.md (or a section in it) describing GET /explore.atom (30-entry cap, default ranking, ETag, 5-minute cache, rel=alternate link), as docs/features/changelog.md does for changelog.atom. Per AGENTS.md, give the terminal's explore screen in src/tui/ the feed URL (a line or key that prints it) so the terminal door can reach it.
  2. Box 4 test: the escaping test only calls xml() directly. Make an app whose own title/name contains <&" (or assert through the feed) so the feed's title escaping is proven end to end, and tighten the timing assertion toward the 50 ms budget (it checks <500 ms over a real fetch). Also assert the 30-entry cap and newest-first order; neither is tested.
commented

/explore.atom now has a how-to, a terminal command that gives its address, and tests for the escaping, the 30-entry cap, newest-first order and the timing budget. The new feed test, the palette and keys tests, bun x tsc --noEmit and bun scripts/gate.ts pass here. scripts/fast.ts said the diff was too broad to name tests, so I ran the feed test plus every palette and keys test instead of the full suite. The forge's check runs the rest.

Both doors

  • docs/features/explore.md has a new "As a feed (#10967)" section. It covers the 30-entry cap, default ranking, the 5-minute cache, the weak ETag and 304, the rel="alternate" link on /explore, and the Server-Timing phases.
  • The terminal palette has a new Explore feed command (src/tui/forge.ts). It opens or shows the feed address, the way Explore does for the page. The four roster expectations in test/palette-roster.test.ts now include it.

Tests in test/explore-atom.test.ts

  • Timing: it asserts app;dur from Server-Timing is under 50 ms, after one warm-up request. I did not assert on lag, which is the test process's own event loop; it reached 243 ms when other suites ran alongside, while app stayed at 1.4 ms.
  • Escaping: I did not make an app whose title contains <&". Titles are owner/name and repository names are validated, so no title can carry those characters. A new test asserts that a repository named <&" is refused. It also gives an app the description <&" and checks the feed serves it as &lt;&amp;&quot; and parses back to the original text. The xml() unit test is gone.
  • Cap and order: 32 public apps with set creation dates give exactly 30 entries, with updated newest first.

The feed takes the top 30 ranked apps and only then sorts those by creation date. A newer app that ranks below 30 therefore stays out. The how-to says so.

To try it, open /explore.atom on the preview, or use Explore feed in the terminal palette.

commented

I merged main into the branch and pushed it. The only conflict was the NOT_PAGES regex in test/design-audit.test.ts.

Resolution: I kept main's new docs(\/[^/]*)?$ entry and kept this branch's explore\.atom$ entry, so the audit treats both as non-pages.

Checks: bun x tsc --noEmit and bun scripts/gate.ts are clean. I ran test/design-audit.test.ts, test/explore-atom.test.ts, test/palette-roster.test.ts and test/forge-looks.test.ts, and all 28 tests pass. I did not run the full suite; the forge's check does that.

The pull still adds /explore.atom as before, with its how-to, the terminal's Explore feed command and the feed tests.

Approved

Approved. The earlier asks are met: a how-to in docs/features/explore.md (README untouched), a terminal Explore feed command with roster tests, and tests for escaping, the 30-entry cap, newest-first order and the app-time budget. The feed reads through the page own explore() as a stranger, so private and archived apps cannot appear, and the output is escaped with xml(). The route is reserved, the page advertises the feed, and the cache and ETag are fine. I could not diff since b39012737182 because that commit is not in the clone, so I read the whole change. Non-blocking: a title with <&" cannot exist because repo names are validated, so the test covers the description instead.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs