From 95476a0d24d505c87ce6be6a6a8090b8ddf2be01 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier <160007691+Flotapponnier@users.noreply.github.com> Date: Mon, 27 Jul 2026 10:29:16 +0200 Subject: [PATCH 1/2] feat: add /bridge hub page with cost + quote latency leaderboards --- src/app/bridge/page.tsx | 489 ++++++++++++++++++++++++++++++++++++ src/lib/bridge-hub-stats.ts | 113 +++++++++ src/lib/sitemap-builder.ts | 1 + 3 files changed, 603 insertions(+) create mode 100644 src/app/bridge/page.tsx create mode 100644 src/lib/bridge-hub-stats.ts diff --git a/src/app/bridge/page.tsx b/src/app/bridge/page.tsx new file mode 100644 index 00000000..dc4ae879 --- /dev/null +++ b/src/app/bridge/page.tsx @@ -0,0 +1,489 @@ +import Link from "next/link"; +import { fetchBridgeHub } from "@/lib/bridge-hub-stats"; +import type { BridgeProviderRow } from "@/lib/bridge-hub-stats"; +import { pageMetadata } from "@/lib/page-metadata"; +import { safeJsonLd, buildBreadcrumbJsonLd } from "@/lib/jsonld"; +import { SITE } from "@/data/site"; + +const DESCRIPTION = + "Live cross-chain bridge benchmarks: cheapest all-in fee and fastest quote API for $300 USDC across Across, deBridge, LI.FI, Mobula, Near Intents and Relay. 4 corridors, refreshed every 5 minutes."; + +export const metadata: import("next").Metadata = pageMetadata({ + path: "/bridge", + title: "Cheapest cross-chain bridge 2026, live ranking", + description: DESCRIPTION, +}); + +export const revalidate = 60; + +export default async function BridgeHubPage() { + const hub = await fetchBridgeHub(); + + const breadcrumbLd = { + "@context": "https://schema.org", + ...buildBreadcrumbJsonLd([ + { name: "Home", item: SITE.url }, + { name: "Bridge benchmarks", item: `${SITE.url}/bridge` }, + ]), + }; + + const itemListLd = hub + ? { + "@context": "https://schema.org", + "@type": "ItemList", + name: "Cross-chain bridge benchmarks by OpenChainBench", + description: DESCRIPTION, + numberOfItems: hub.bridgeCount, + itemListElement: hub.providers.map((p, i) => ({ + "@type": "ListItem", + position: i + 1, + name: p.name, + url: `${SITE.url}/products/${p.slug}`, + })), + } + : null; + + const byFee = hub + ? [...hub.providers].sort( + (a, b) => (a.feep50 ?? Infinity) - (b.feep50 ?? Infinity), + ) + : []; + + const bySpeed = hub + ? [...hub.providers] + .filter((p) => p.quotep50 != null) + .sort((a, b) => (a.quotep50 ?? Infinity) - (b.quotep50 ?? Infinity)) + : []; + + return ( +
+ {/* biome-ignore lint/security/noDangerouslySetInnerHtml: serialized via safeJsonLd */} +