diff --git a/next.config.ts b/next.config.ts
index 458105e14..f21e589b9 100644
--- a/next.config.ts
+++ b/next.config.ts
@@ -195,6 +195,10 @@ const nextConfig: NextConfig = {
"linea",
"scroll",
"mantle",
+ "gnosis",
+ "sonic",
+ "solana",
+ "polkadot",
];
const rpcClusterRedirects = RPC_CLUSTER_CHAINS.map((chain) => ({
source: `/benchmarks/rpc-capabilities/${chain}`,
diff --git a/src/app/benchmarks/[slug]/page.tsx b/src/app/benchmarks/[slug]/page.tsx
index 5c861d05a..4b44bda4b 100644
--- a/src/app/benchmarks/[slug]/page.tsx
+++ b/src/app/benchmarks/[slug]/page.tsx
@@ -13,6 +13,7 @@ import { TerminalFillAudit } from "@/components/terminal-fill-audit";
import { Breadcrumb } from "@/components/breadcrumb";
import { ChainHeadingsSummary } from "@/components/chain-headings-summary";
import { CompareThisBench } from "@/components/compare-this-bench";
+import { isThinRpcBench } from "@/lib/provider-filters";
import { PublicEndpointsSection } from "@/components/public-endpoints-section";
import { CitationBar } from "@/components/citation-bar";
import { LiveIndicator } from "@/components/live-indicator";
@@ -124,7 +125,7 @@ export async function generateMetadata({
// provider leaderboard has no comparative value and no search demand.
// noindex/follow keeps crawl equity flowing without letting an
// empty-looking table rank for "fastest X rpc".
- const metaThinRpc = b.category === "RPCs" && (b.results?.length ?? 0) < 3;
+ const metaThinRpc = isThinRpcBench(b);
const metaTitle = b.seoTitle ?? b.title;
// Description precedence (most-to-least specific):
// 1. `seo_description` from the YAML - hand-crafted snippet with the
diff --git a/src/app/benchmarks/page.tsx b/src/app/benchmarks/page.tsx
index 1a76bd333..d2762c6c7 100644
--- a/src/app/benchmarks/page.tsx
+++ b/src/app/benchmarks/page.tsx
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import { getBenchmarksSafe, toBenchmarkCardData } from "@/data/benchmarks";
+import { isThinRpcBench } from "@/lib/provider-filters";
import { BenchmarkGrid } from "@/components/benchmark-grid";
import { safeJsonLd } from "@/lib/jsonld";
@@ -28,7 +29,9 @@ export const metadata: Metadata = {
};
export default async function BenchmarksPage() {
- const benchmarks = await getBenchmarksSafe();
+ // Thin chain RPC benches (< 3 providers) are noindex on their own page;
+ // the index does not link them (see isThinRpcBench).
+ const benchmarks = (await getBenchmarksSafe()).filter((b) => !isThinRpcBench(b));
// ItemList + BreadcrumbList JSON-LD so search engines and LLMs see the
// page as a structured registry (the data is already in the DOM but
diff --git a/src/app/rpc/page.tsx b/src/app/rpc/page.tsx
index afdaad4c5..7c696dc6b 100644
--- a/src/app/rpc/page.tsx
+++ b/src/app/rpc/page.tsx
@@ -1,5 +1,6 @@
import Link from "next/link";
import { fetchRpcHub, NON_CHAIN_RPC_SLUGS } from "@/lib/rpc-hub-stats";
+import { loadSitemapBlob } from "@/lib/sitemap-blob";
import { getSpecs } from "@/lib/spec";
import { RpcHubTabs } from "@/components/rpc-hub-tabs";
import { pageMetadata } from "@/lib/page-metadata";
@@ -31,11 +32,17 @@ export const metadata: import("next").Metadata = pageMetadata({
export const revalidate = 3600;
export default async function RpcHubPage() {
- const [snapshot, specs] = await Promise.all([fetchRpcHub(), getSpecs()]);
+ const [snapshot, specs, sitemapBlob] = await Promise.all([fetchRpcHub(), getSpecs(), loadSitemapBlob()]);
// Spec-derived chain list: stable across snapshot outages, so the
// JSON-LD ItemList and the empty state never churn with data blips.
+ // Restricted to the benches the worker publishes in the sitemap: a chain
+ // bench under the thin gate is noindex on its own page and must not be
+ // linked from here (36 such links on 2026-09-19). Without the blob, no
+ // restriction rather than an empty hub.
+ const indexable = sitemapBlob ? new Set(sitemapBlob.benches.map((b) => b.slug)) : null;
const rpcSpecs = specs
.filter((s) => s.slug.endsWith("-rpc") && !NON_CHAIN_RPC_SLUGS.has(s.slug))
+ .filter((s) => !indexable || indexable.has(s.slug))
.sort((a, b) => a.slug.localeCompare(b.slug));
// Keyed / API-key RPC benches (e.g. keyed-rpc-robinhood). These do NOT
// belong in the no-key chain matrix above (different tier, and the
@@ -61,7 +68,7 @@ export default async function RpcHubPage() {
"@type": "ItemList",
name: "Per-chain free RPC benchmarks by OpenChainBench",
description:
- "Live per-chain benchmarks of free, no-key public RPC endpoints: latency, reliability and archive depth measured every 15 seconds from 3 regions.",
+ "Live per-chain benchmarks of free, no-key public RPC endpoints: latency, reliability and archive depth measured every 60 seconds from 3 regions.",
numberOfItems: rpcSpecs.length,
itemListElement: rpcSpecs.map((s, i) => ({
"@type": "ListItem",
@@ -119,7 +126,7 @@ export default async function RpcHubPage() {
Every free, no-key public RPC endpoint, measured per chain with
the same probe: one identical{" "}
eth_getBlockByNumber("latest", false) call with a
- rotating request id (defeats CDN body-keyed caches) every 15
+ rotating request id (defeats CDN body-keyed caches) every 60
seconds from 3 regions (N. Virginia, Amsterdam, Singapore). The matrix below folds the per-chain leaderboards
into one view: fastest provider per chain, fastest per region,
and which gateway covers your whole multichain stack. Headline
@@ -277,7 +284,7 @@ export default async function RpcHubPage() {
Each chain row aggregates that chain's dedicated bench: an
identical JSON-RPC POST (eth_getBlockByNumber("latest", false) with
- rotating request id, or the chain's equivalent head call) sent every 15 seconds to
+ rotating request id, or the chain's equivalent head call) sent every 60 seconds to
every free, no-key public endpoint from us-east, eu-west and
Singapore. Headline figures are the 50th percentile of
client-side round-trip latency over the trailing 24 hours,
diff --git a/src/components/benchmark-body.tsx b/src/components/benchmark-body.tsx
index 96db79a7a..7af788124 100644
--- a/src/components/benchmark-body.tsx
+++ b/src/components/benchmark-body.tsx
@@ -999,7 +999,7 @@ export function BenchmarkBody({
>
) : (
<>
-
+
By region
+