From 037a5a81ea5f99f4975debce1fb4b4f6b9ae80e2 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sun, 6 Sep 2026 03:13:29 +0000 Subject: [PATCH] Serve the board index at /leaderboard.json Next matches on path segments, so /leaderboard.json is a sibling of /leaderboard rather than a child: the catch-all under leaderboard/[[...path]] never saw it and the request fell through to the feed route, which answered 'no such feed: leaderboard'. Only visible in production, because a test that calls the route handler directly bypasses the router that makes the decision. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_0144uEVbZK3jdaQkwcLYTXPE --- apps/web/src/app/leaderboard.json/route.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 apps/web/src/app/leaderboard.json/route.js diff --git a/apps/web/src/app/leaderboard.json/route.js b/apps/web/src/app/leaderboard.json/route.js new file mode 100644 index 0000000..379dc78 --- /dev/null +++ b/apps/web/src/app/leaderboard.json/route.js @@ -0,0 +1,19 @@ +import { leaderboard } from '../../lib/leaderboard.js'; + +/** + * The board index, at `/leaderboard.json`. + * + * A route of its own because Next matches on path segments: `/leaderboard.json` + * is a sibling of `/leaderboard`, not a child, so the catch-all under + * `leaderboard/[[...path]]` never sees it and the request falls through to the + * feed route, which answers "no such feed: leaderboard". The package documents + * this path as the index, and on a framework that hands every path to one + * handler it is the index; here it has to be spelled out. + */ +export const dynamic = 'force-dynamic'; + +export async function GET(request) { + return (await leaderboard().handle(request)) ?? new Response('Not found', { status: 404 }); +} + +export const HEAD = GET;