diff --git a/src/components/CCIP/Tables/VerifiersTable.tsx b/src/components/CCIP/Tables/VerifiersTable.tsx
new file mode 100644
index 00000000000..dc79bf8753e
--- /dev/null
+++ b/src/components/CCIP/Tables/VerifiersTable.tsx
@@ -0,0 +1,124 @@
+import Address from "~/components/AddressReact.tsx"
+import "./Table.css"
+import { Environment, Verifier, getVerifierTypeDisplay } from "~/config/data/ccip/index.ts"
+import TableSearchInput from "./TableSearchInput.tsx"
+import { useState } from "react"
+import {
+ getExplorerAddressUrl,
+ fallbackVerifierIconUrl,
+ getChainIcon,
+ getTitle,
+ directoryToSupportedChain,
+ getExplorer,
+ getChainTypeAndFamily,
+} from "~/features/utils/index.ts"
+
+interface VerifiersTableProps {
+ verifiers: Verifier[]
+}
+
+function VerifiersTable({ verifiers }: VerifiersTableProps) {
+ const [search, setSearch] = useState("")
+
+ // Transform verifiers data to include network information
+ const verifiersWithNetworkInfo = verifiers.map((verifier) => {
+ const supportedChain = directoryToSupportedChain(verifier.network)
+ const networkName = getTitle(supportedChain) || verifier.network
+ const networkLogo = getChainIcon(supportedChain) || ""
+ const explorer = getExplorer(supportedChain)
+ const { chainType } = getChainTypeAndFamily(supportedChain)
+
+ return {
+ ...verifier,
+ networkName,
+ networkLogo,
+ supportedChain,
+ explorer,
+ chainType,
+ }
+ })
+
+ const filteredVerifiers = verifiersWithNetworkInfo.filter(
+ (verifier) =>
+ verifier.name.toLowerCase().includes(search.toLowerCase()) ||
+ verifier.networkName.toLowerCase().includes(search.toLowerCase()) ||
+ verifier.address.toLowerCase().includes(search.toLowerCase()) ||
+ getVerifierTypeDisplay(verifier.type).toLowerCase().includes(search.toLowerCase())
+ )
+
+ return (
+ <>
+
+
+ Verifiers ({verifiers.length})
+
+
+
+
+
+
+
+ | Verifier |
+ Network |
+ Verifier address |
+ Verifier type |
+
+
+
+ {filteredVerifiers.map((verifier, index) => (
+
+
+
+
+ {
+ currentTarget.onerror = null // prevents looping
+ currentTarget.src = fallbackVerifierIconUrl
+ }}
+ />
+
+ {verifier.name}
+
+ |
+
+
+
+ {
+ currentTarget.onerror = null // prevents looping
+ currentTarget.src = fallbackVerifierIconUrl
+ }}
+ />
+
+ {verifier.networkName}
+
+ |
+
+
+ |
+ {getVerifierTypeDisplay(verifier.type)} |
+
+ ))}
+
+
+
{filteredVerifiers.length === 0 && <>No verifiers found>}
+
+ >
+ )
+}
+
+export default VerifiersTable
diff --git a/src/components/CCIP/VerifierGrid/VerifierGrid.tsx b/src/components/CCIP/VerifierGrid/VerifierGrid.tsx
index 5191cb5925d..133dbb95a97 100644
--- a/src/components/CCIP/VerifierGrid/VerifierGrid.tsx
+++ b/src/components/CCIP/VerifierGrid/VerifierGrid.tsx
@@ -20,7 +20,7 @@ function VerifierGrid({ verifiers, environment }: VerifierGridProps) {
items={verifiers}
initialDisplayCount={BEFORE_SEE_MORE}
seeMoreLabel="View all verifiers"
- seeMoreLink="/verifiers"
+ seeMoreLink={`/ccip/directory/${environment}/verifiers`}
renderItem={(verifier) => {
const subtitle = `${verifier.totalNetworks} ${verifier.totalNetworks === 1 ? "network" : "networks"}`
const logoElement = (
@@ -34,8 +34,8 @@ function VerifierGrid({ verifiers, environment }: VerifierGridProps) {
logo={logoElement}
title={verifier.name}
subtitle={subtitle}
- link={`/ccip/directory/${environment}/verifier/${verifier.id}`}
- ariaLabel={`View ${verifier.name} verifier details`}
+ link={`/ccip/directory/${environment}/verifiers`}
+ ariaLabel={`View verifiers page for ${verifier.name}`}
/>
)
}}
diff --git a/src/components/CCIP/Verifiers/Verifiers.astro b/src/components/CCIP/Verifiers/Verifiers.astro
new file mode 100644
index 00000000000..2672f983332
--- /dev/null
+++ b/src/components/CCIP/Verifiers/Verifiers.astro
@@ -0,0 +1,98 @@
+---
+import CcipDirectoryLayout from "~/layouts/CcipDirectoryLayout.astro"
+import { getEntry, render } from "astro:content"
+import { getAllNetworks, getAllVerifiers, getSearchLanes, Version, Environment } from "~/config/data/ccip"
+import Table from "~/components/CCIP/Tables/VerifiersTable"
+import { getAllUniqueVerifiers } from "~/config/data/ccip/data.ts"
+import { DOCS_BASE_URL } from "~/utils/structuredData"
+import ChainHero from "~/components/CCIP/ChainHero/ChainHero"
+import "./Verifiers.css"
+
+interface Props {
+ environment: Environment
+}
+
+const { environment } = Astro.props as Props
+
+const entry = await getEntry("ccip", "index")
+if (!entry) {
+ throw new Error('Could not find "ccip/index" doc. Check src/content/ccip/index.mdx!')
+}
+
+const { headings } = await render(entry)
+
+const networks = getAllNetworks({ filter: environment })
+
+const allVerifiers = getAllVerifiers({
+ environment,
+ version: Version.V1_2_0,
+})
+
+const uniqueVerifiers = getAllUniqueVerifiers({
+ environment,
+ version: Version.V1_2_0,
+})
+
+const searchLanes = getSearchLanes({ environment })
+
+// Generate dynamic metadata for verifiers page
+const environmentText = environment === Environment.Mainnet ? "Mainnet" : "Testnet"
+const verifiersMetadata = {
+ title: `CCIP Verifiers - ${environmentText} Networks`,
+ description: `View all CCIP verifiers across ${environmentText} networks. Explore ${allVerifiers.length} verifiers, their addresses, types, and supported networks for cross-chain verification.`,
+ image: "/assets/product-logos/ccip-logo.svg",
+ excerpt: `CCIP verifiers ${environmentText.toLowerCase()} networks addresses types committee api cross-chain verification blockchain interoperability`,
+}
+
+// Generate structured data for verifiers page
+const currentPath = new URL(Astro.request.url).pathname
+const canonicalForJsonLd = `${DOCS_BASE_URL}${currentPath}`
+---
+
+
+ ({
+ id: verifier.id,
+ totalNetworks: verifier.totalNetworks,
+ logo: verifier.logo,
+ }))}
+ lanes={searchLanes}
+ environment={environment}
+ breadcrumbItems={[
+ {
+ name: "CCIP Directory",
+ url: `/ccip/directory/${environment}`,
+ },
+ {
+ name: "Verifiers",
+ url: `/ccip/directory/${environment}/verifiers`,
+ },
+ ]}
+ client:load
+ />
+
+
+
diff --git a/src/components/CCIP/Verifiers/Verifiers.css b/src/components/CCIP/Verifiers/Verifiers.css
new file mode 100644
index 00000000000..eda464e886c
--- /dev/null
+++ b/src/components/CCIP/Verifiers/Verifiers.css
@@ -0,0 +1,43 @@
+.layout {
+ margin: 0 auto;
+ padding: var(--space-6x);
+}
+
+.layout h2 {
+ color: var(--gray-900);
+ font-size: 22px;
+ line-height: var(--space-10x);
+ padding-bottom: var(--space-4x);
+ border-bottom: 1px solid var(--gray-200);
+ margin-bottom: var(--space-6x);
+}
+
+.layout h2 span {
+ color: var(--gray-400);
+ font-weight: 600;
+ letter-spacing: 0.5px;
+}
+
+.networks__grid {
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: var(--space-8x);
+}
+
+.tokens__grid {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: var(--space-8x);
+}
+
+@media (min-width: 50em) {
+ .layout {
+ max-width: 1500px;
+ }
+}
+
+@media (min-width: 992px) {
+ .layout {
+ padding: var(--space-10x) var(--space-8x);
+ }
+}
diff --git a/src/pages/ccip/directory/mainnet/verifiers/index.astro b/src/pages/ccip/directory/mainnet/verifiers/index.astro
new file mode 100644
index 00000000000..07aad33d482
--- /dev/null
+++ b/src/pages/ccip/directory/mainnet/verifiers/index.astro
@@ -0,0 +1,8 @@
+---
+import Verifiers from "~/components/CCIP/Verifiers/Verifiers.astro"
+import { Environment } from "~/config/data/ccip"
+
+export const prerender = true
+---
+
+
diff --git a/src/pages/ccip/directory/testnet/verifiers/index.astro b/src/pages/ccip/directory/testnet/verifiers/index.astro
new file mode 100644
index 00000000000..a6101109fd7
--- /dev/null
+++ b/src/pages/ccip/directory/testnet/verifiers/index.astro
@@ -0,0 +1,8 @@
+---
+import Verifiers from "~/components/CCIP/Verifiers/Verifiers.astro"
+import { Environment } from "~/config/data/ccip"
+
+export const prerender = true
+---
+
+