Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/lib/removed-benches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,30 @@ export const REMOVED_BENCH_SLUGS = new Set([
// indexed URL. Bench 077 tokenized-stock-peg + 079 weekend-drift
// (static peg measurements) stay on prod as the honest signal.
"tokenized-stock-arb-latency",
// token-trade-coverage (090) dropped 2026-07-24: self-baseline bias
// (Mobula pinned at 100% because it returned the highest raw counts).
// Spec + harness removed; rebuild needs RPC-derived ground truth.
"token-trade-coverage",
// staging pipeline, held back until validated / announced
"indexing-freshness",
"rpc-keyed-latency",
"explorer-chain-coverage",
"portfolio-chain-coverage",
]);

/**
* Provider slugs whose /products/<slug> route should return 410 Gone
* rather than 404. Populated when a provider that once had a product
* page loses ALL its bench appearances.
*
* Enforced only in src/middleware.ts. The /products/[slug] page
* already calls notFound() when getProvider() returns null; this set
* exists purely to swap the resulting 404 for a 410 on prod.
*/
export const REMOVED_PRODUCT_SLUGS = new Set([
// bitquery was only referenced in bench 090 token-trade-coverage,
// dropped 2026-07-24. Product page was live briefly, so Google
// likely indexed the URL. 410 speeds de-indexing.
"bitquery",
]);

10 changes: 10 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ const CANONICAL_NO_QUERY = new Set([
import {
REMOVED_ANSWER_SLUGS,
REMOVED_BENCH_SLUGS,
REMOVED_PRODUCT_SLUGS,
RENAMED_BENCH_SLUGS,
} from "@/lib/removed-benches";
export { REMOVED_BENCH_SLUGS };

const BENCH_PATH = /^\/benchmarks\/([a-z0-9][a-z0-9-]{0,79})\/?$/;
const ANSWER_PATH = /^\/answers\/([a-z0-9][a-z0-9-]{0,79})\/?$/;
const PRODUCT_PATH = /^\/products\/([a-z0-9][a-z0-9-]{0,79})\/?$/;
// `/compare/<a>-vs-<b>` with both sides as standard provider slug
// shapes (lowercase alphanumeric + hyphens). The `-vs-` delimiter is
// matched literally; provider slugs themselves can contain hyphens
Expand Down Expand Up @@ -93,6 +95,13 @@ export function middleware(req: NextRequest) {
{ status: 410, headers: { "Content-Type": "text/html; charset=utf-8" } },
);
}
const p = pathname.match(PRODUCT_PATH);
if (p && REMOVED_PRODUCT_SLUGS.has(p[1])) {
return new NextResponse(
`<!doctype html><html lang="en"><head><meta charset="utf-8"><title>410 Gone</title><meta name="robots" content="noindex"></head><body><h1>410 Gone</h1><p>This product page has been retired because the provider is no longer measured in any active benchmark. See the <a href="/products">current catalog</a>.</p></body></html>`,
{ status: 410, headers: { "Content-Type": "text/html; charset=utf-8" } },
);
}
}

const compareMatch = pathname.match(COMPARE_PATH);
Expand Down Expand Up @@ -130,5 +139,6 @@ export const config = {
"/benchmarks/:slug*",
"/answers/:slug*",
"/compare/:slug*",
"/products/:slug*",
],
};
Loading