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
7 changes: 7 additions & 0 deletions src/app/compare/[slug]/page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -84,9 +84,16 @@ function parseAdHocSlug(slug: string): { a: string; b: string } | null {
* Returns a synthetic ComparePair so the rest of the route works
* unchanged. Returns null when any of those checks fail.
*/
// HL builder addresses (0x...) leak into the provider catalog because
// the HL bench tracks builders by raw on-chain address. They have no
// search demand as compare targets, only pollute crawl budget.
// Drop them at the entry so /compare/0x...-vs-* 404s cleanly.
const HEX_SLUG_RE = /^0x[0-9a-f]{4,}$/i;

async function resolveAdHocPair(slug: string): Promise<ComparePair | null> {
const parsed = parseAdHocSlug(slug);
if (!parsed) return null;
if (HEX_SLUG_RE.test(parsed.a) || HEX_SLUG_RE.test(parsed.b)) return null;
const [first, second] = [parsed.a, parsed.b].sort();
if (slug !== `${first}-vs-${second}`) return null;
const [a, b] = await Promise.all([
Expand Down
24 changes: 24 additions & 0 deletions src/app/sitemap.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import { statSync } from "node:fs";
import path from "node:path";
import type { MetadataRoute } from "next";
import { getBenchmarks } from "@/data/benchmarks";
import { COMPARE_PAIRS } from "@/data/compare-pairs";
import { loadAllAlternatives } from "@/lib/alternatives";
import { loadAllAnswers } from "@/lib/answers";
import { CHAIN_BY_SLUG, CHAINS, getBenchmarksForChain } from "@/lib/chains";
Expand DownExpand Up@@ -286,13 +287,36 @@ async function buildFullSitemap(): Promise<MetadataRoute.Sitemap> {
)
).filter((r): r is NonNullable<typeof r> => r !== null);

// Curated compare pairs. Both providers are pre-validated to exist
// and share at least one bench (criteria documented in
// src/data/compare-pairs.ts). Defensive recheck via getProvider to
// skip any pair whose provider was removed since publication.
const compareRoutes: MetadataRoute.Sitemap = (
await Promise.all(
COMPARE_PAIRS.map(async (pair) => {
const [a, b] = await Promise.all([
getProvider(pair.providerA),
getProvider(pair.providerB),
]);
if (!a || !b) return null;
return {
url: `${SITE.url}/compare/${pair.slug}`,
lastModified: catalogTs,
changeFrequency: "weekly" as const,
priority: 0.7,
};
}),
)
).filter((r): r is NonNullable<typeof r> => r !== null);

return [
...staticRoutes,
...benchmarkRoutes,
...providerRoutes,
...alternativeRoutes,
...answerRoutes,
...chainRoutes,
...compareRoutes,
];
}

Expand Down
Loading