-
-
- {tCommon("listing-policy-disclaimer")}{" "}
-
- {t("listing-policy-raise-issue-link")}
+
+
+
+ {t("page-get-eth-cex-link-desc")}
-
-
-
-
-
-
- {t("page-get-eth-new-to-eth")}{" "}
-
- {t("page-get-eth-whats-eth-link")}
-
-
-
-
-
-
-
-
-
{t("page-get-eth-exchanges-header")}
-
- {t("page-get-eth-exchanges-intro")}
-
-
- {/* CLIENT SIDE */}
-
-
-
+
+
+
+ {t("page-get-eth-daos-link-desc")}
+
+
+
+
+ {t("page-get-eth-wallets-link")}
+
+
+
+ }
+ >
+
{t("page-get-eth-try-dex")}
+
+
+
+ {t("page-get-eth-wallets-link")}
+
+
+
+
+ {t("page-get-eth-staking-link-desc")}
+
+
-
-
-
- {t("page-get-eth-dexs")}
-
-
-
-
- {t("page-get-eth-what-are-DEX's")}
-
- {t("page-get-eth-dexs-desc")}
-
- {t("page-get-eth-dexs-desc-2")}{" "}
-
- {t("page-get-eth-smart-contract-link")}
+
+
+
+ {tCommon("listing-policy-disclaimer")}{" "}
+
+ {t("listing-policy-raise-issue-link")}
+
+
+
+
+
+
+ {t("page-get-eth-new-to-eth")}{" "}
+
+ {t("page-get-eth-whats-eth-link")}
+
+
+
+
+
+
+
+
+
{t("page-get-eth-exchanges-header")}
+
+ {t("page-get-eth-exchanges-intro")}
-
{t("page-get-eth-dexs-desc-3")}
-
{t("page-get-eth-need-wallet")}
-
- {t("page-get-eth-get-wallet-btn")}
-
-
-
-
-
-
-
-
-
-
-
-
- {t("page-get-eth-other-cryptos")}
-
- {t("page-get-eth-swapping")}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {t("page-get-eth-keep-it-safe")}
-
-
-
-
-
- {t("page-get-eth-community-safety")}
-
-
-
-
-
-
- {t("page-get-eth-description")}
- {t("page-get-eth-security")}
-
+ {/* CLIENT SIDE */}
+
+
+
+
+
+
+
+
+ {t("page-get-eth-dexs")}
+
+
- {t("page-get-eth-protect-eth-in-wallet")}
+ {t("page-get-eth-what-are-DEX's")}
- {t("page-get-eth-protect-eth-desc")}
-
- {t("page-get-eth-your-address-wallet-link")}
-
+ {t("page-get-eth-dexs-desc")}
+
+ {t("page-get-eth-dexs-desc-2")}{" "}
+
+ {t("page-get-eth-smart-contract-link")}
+
+
+ {t("page-get-eth-dexs-desc-3")}
+ {t("page-get-eth-need-wallet")}
+
+ {t("page-get-eth-get-wallet-btn")}
+
+
+
+
+
+
+
+
+
- {t("page-get-eth-your-address")}
+ {t("page-get-eth-other-cryptos")}
- {t("page-get-eth-your-address-desc")}
-
-
- 0x0125e2478d69eXaMpLe81766fef5c120d30fb53f
-
-
- {t("page-get-eth-do-not-copy")}
-
-
- {t("page-get-eth-your-address-desc-3")}
+ {t("page-get-eth-swapping")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {t("page-get-eth-keep-it-safe")}
+
+
+
- {t("page-get-eth-wallet-instructions")}
+ {t("page-get-eth-community-safety")}
- {t("page-get-eth-wallet-instructions-lost")}
+
-
-
-
-
-
-
-
-
- {t("page-get-eth-checkout-dapps-btn")}
-
-
-
+
+
+ {t("page-get-eth-description")}
+ {t("page-get-eth-security")}
+
+
+
+ {t("page-get-eth-protect-eth-in-wallet")}
+
+ {t("page-get-eth-protect-eth-desc")}
+
+ {t("page-get-eth-your-address-wallet-link")}
+
+
+
+
+ {t("page-get-eth-your-address")}
+
+ {t("page-get-eth-your-address-desc")}
+
+
+ 0x0125e2478d69eXaMpLe81766fef5c120d30fb53f
+
+
+ {t("page-get-eth-do-not-copy")}
+
+
+ {t("page-get-eth-your-address-desc-3")}
+
+
+
+ {t("page-get-eth-wallet-instructions")}
+
+ {t("page-get-eth-wallet-instructions-lost")}
+
+
+
+
+
+
+
+
+
+
+ {t("page-get-eth-checkout-dapps-btn")}
+
+
+
-
+
-
-
-
+
+
+
+ >
)
}
@@ -433,6 +443,6 @@ export async function generateMetadata({
locale,
slug: ["get-eth"],
title: t("page-get-eth-meta-title"),
- description: t("page-get-eth-meta-desc"),
+ description: t("page-get-eth-meta-description"),
})
}
diff --git a/app/[locale]/layer-2/_components/layer-2.tsx b/app/[locale]/layer-2/_components/layer-2.tsx
index ea7c4fdcc3f..9a45cfecba7 100644
--- a/app/[locale]/layer-2/_components/layer-2.tsx
+++ b/app/[locale]/layer-2/_components/layer-2.tsx
@@ -85,425 +85,440 @@ const Layer2Hub = ({
]
return (
-
-
+ <>
+
+
-
-
-
-
{t("page-layer-2-powered-by-ethereum-title")}
-
-
- {t("page-layer-2-powered-by-ethereum-description-1")}{" "}
-
- {t("page-layer-2-powered-by-ethereum-description-2")}
-
-
{t("page-layer-2-powered-by-ethereum-description-3")}
-
-
-
+
+
+
+
{t("page-layer-2-powered-by-ethereum-title")}
+
+
+ {t("page-layer-2-powered-by-ethereum-description-1")}{" "}
+
+ {t("page-layer-2-powered-by-ethereum-description-2")}
+
+
{t("page-layer-2-powered-by-ethereum-description-3")}
+
+
+
+
-
-
-
-
-
-
-
- $
- {(
- growThePieData.dailyTxCosts["ethereum"] || 0
- ).toLocaleString(locale as Lang, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- })}
-
-
- {t("page-layer-2-blockchain-transaction-cost")}
-
+
+
+
+
+
+
+ $
+ {(
+ growThePieData.dailyTxCosts["ethereum"] || 0
+ ).toLocaleString(locale as Lang, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ })}
+
+
+ {t("page-layer-2-blockchain-transaction-cost")}
+
+
-
-
-
-
-
- $
- {medianTxCost.toLocaleString(locale as Lang, {
- minimumFractionDigits: 2,
- maximumFractionDigits: 3,
- })}
-
-
- {t("page-layer-2-networks-transaction-cost")}
-
+
+
+
+
+ $
+ {medianTxCost.toLocaleString(locale as Lang, {
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 3,
+ })}
+
+
+ {t("page-layer-2-networks-transaction-cost")}
+
+
-
-
-
-
{t("page-layer-2-network-of-networks-title")}
-
- {t("page-layer-2-network-of-networks-description")}
-
-
- {/* Outer ring */}
-
-
- {/* Top logo */}
-
-
-
- {/* Bottom right logo */}
-
-
-
- {/* Bottom left logo */}
-
-
+
+
+
{t("page-layer-2-network-of-networks-title")}
+
+ {t("page-layer-2-network-of-networks-description")}
+
+
+ {/* Outer ring */}
+
+
+ {/* Top logo */}
+
+
+
+ {/* Bottom right logo */}
+
+
+
+ {/* Bottom left logo */}
+
+
+
-
- {/* Middle ring */}
-
-
- {/* Top logo */}
-
-
-
- {/* Bottom right logo */}
-
-
-
- {/* Bottom left logo */}
-
-
+ {/* Middle ring */}
+
+
+ {/* Top logo */}
+
+
+
+ {/* Bottom right logo */}
+
+
+
+ {/* Bottom left logo */}
+
+
+
-
- {/* Inner ring */}
-
-
- {/* Top logo */}
-
-
-
- {/* Bottom right logo */}
-
-
+ {/* Inner ring */}
+
+
+ {/* Top logo */}
+
+
+
+ {/* Bottom right logo */}
+
+
+
+ {/* Bottom left logo */}
+
+
+
- {/* Bottom left logo */}
-
+
+ {/* Center Ethereum Logo */}
+
-
- {/* Center Ethereum Logo */}
-
-
-
-
-
-
- {calloutCards.map((card, idx) => {
- return (
-
-
-
- )
- })}
-
-
-
-
-
-
{t("page-layer-2-ready-to-start-title")}
-
{t("page-layer-2-ready-to-start-description")}
-
-
- {t("page-layer-2-ready-to-start-button")}
-
-
-
-
-
-
-
-
- {userRandomL2s.map((l2, idx) => {
+
+
+ {calloutCards.map((card, idx) => {
return (
-
-
-
-
-
-
-
{l2.name}
-
{t(l2.description)}
-
-
-
-
- {t("page-layer-2-go")}
-
-
+
+
)
})}
-
-
-
-
-
{t("page-layer-2-powered-by-ethereum-title")}
-
-
-
-
-
-
-
-
-
-
{t("page-layer-2-why-do-we-need-multiple-networks-1")}
-
{t("page-layer-2-why-do-we-need-multiple-networks-2")}
+
+
+
{t("page-layer-2-ready-to-start-title")}
+
{t("page-layer-2-ready-to-start-description")}
- {t("common:learn-more")}
+ {t("page-layer-2-ready-to-start-button")}
-
-
-
{t("page-layer-2-faq-title")}
-
-
-
-
- {t("page-layer-2-faq-ExpandableCard-1-description-1")}{" "}
-
- {t("common:nav-ethereum-networks")}
-
- {t("page-layer-2-period")}
-
-
{t("page-layer-2-faq-ExpandableCard-1-description-2")}
+
+
+
+ {userRandomL2s.map((l2, idx) => {
+ return (
+
+
+
+
+
+
+
{l2.name}
+
{t(l2.description)}
+
+
+
+
+ {t("page-layer-2-go")}
+
+
+
+ )
+ })}
-
-
-
-
- {t("page-layer-2-faq-ExpandableCard-2-description-1")}{" "}
-
- {t("page-layer-2-faq-ExpandableCard-2-link")}
-
- {t("page-layer-2-period")}
-
-
{t("page-layer-2-faq-ExpandableCard-2-description-2")}
+
+
+
+
+
{t("page-layer-2-powered-by-ethereum-title")}
+
-
-
- {t("page-layer-2-faq-ExpandableCard-3-description")}
-
-
- {t("page-layer-2-faq-ExpandableCard-4-description")}
-
+
-
-
-
-
-
- {t("common:nav-networks-explore-networks-label")}
-
+
+
+
+
+
+
{t("page-layer-2-why-do-we-need-multiple-networks-1")}
+
{t("page-layer-2-why-do-we-need-multiple-networks-2")}
+
+
+ {t("common:learn-more")}
+
+
+
-
-
+
+
+
{t("page-layer-2-faq-title")}
-
+
+
+ {t("page-layer-2-faq-ExpandableCard-1-description-1")}{" "}
+
+ {t("common:nav-ethereum-networks")}
+
+ {t("page-layer-2-period")}
+
+
{t("page-layer-2-faq-ExpandableCard-1-description-2")}
+
+
+
+
+
+ {t("page-layer-2-faq-ExpandableCard-2-description-1")}{" "}
+
+ {t("page-layer-2-faq-ExpandableCard-2-link")}
+
+ {t("page-layer-2-period")}
+
+
{t("page-layer-2-faq-ExpandableCard-2-description-2")}
+
+
+
+ {t("page-layer-2-faq-ExpandableCard-3-description")}
+
+
- {t("common:learn-more")}
-
+
{t("page-layer-2-faq-ExpandableCard-4-description")}
+
-
-
-
+
+
+
+
+
+
+ {t("common:nav-networks-explore-networks-label")}
+
+
+
+
+
+
+ {t("common:learn-more")}
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/layer-2/learn/page-jsonld.tsx b/app/[locale]/layer-2/learn/page-jsonld.tsx
new file mode 100644
index 00000000000..ca37ab0cfd9
--- /dev/null
+++ b/app/[locale]/layer-2/learn/page-jsonld.tsx
@@ -0,0 +1,119 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function Layer2LearnPageJsonLD({
+ locale,
+ lastEditLocaleTimestamp,
+ contributors,
+}: {
+ locale: Lang | undefined
+ lastEditLocaleTimestamp: string
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-layer-2-learn",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/layer-2/learn/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Layer 2 Learn page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-layer-2-learn-meta-title"),
+ description: t("page-layer-2-learn-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: "Layer 2",
+ item: normalizeUrlForJsonLd(locale, "/layer-2/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 3,
+ name: t("page-layer-2-learn-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the article content about learning Layer 2
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-layer-2-learn-title"),
+ description: t("page-layer-2-learn-description"),
+ image: "https://ethereum.org/images/layer-2/learn-hero.png", // TODO: adjust value when the old theme breakpoints are removed (src/theme.ts)
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ contributor: contributorList,
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ dateModified: lastEditLocaleTimestamp,
+ }
+
+ return
+}
diff --git a/app/[locale]/layer-2/learn/page.tsx b/app/[locale]/layer-2/learn/page.tsx
index 066b5aa2d2f..111969bd053 100644
--- a/app/[locale]/layer-2/learn/page.tsx
+++ b/app/[locale]/layer-2/learn/page.tsx
@@ -14,6 +14,7 @@ import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import LearnPage from "./_components/learn"
+import Layer2LearnPageJsonLD from "./page-jsonld"
const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const { locale } = await params
@@ -35,9 +36,15 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
return (
+
)
diff --git a/app/[locale]/layer-2/networks/_components/networks.tsx b/app/[locale]/layer-2/networks/_components/networks.tsx
index d1b707a622c..91ad75a55e3 100644
--- a/app/[locale]/layer-2/networks/_components/networks.tsx
+++ b/app/[locale]/layer-2/networks/_components/networks.tsx
@@ -25,82 +25,84 @@ const Layer2Networks = ({ layer2Data, locale, mainnetData }) => {
}
return (
-
-
+ <>
+
+
-
+
-
-
-
{t("page-layer-2-networks-more-advanced-title")}
-
-
- {t("page-layer-2-networks-more-advanced-descripton-1")}{" "}
-
- {t("page-layer-2-networks-more-advanced-descripton-2")}
-
-
-
{t("page-layer-2-networks-more-advanced-descripton-3")}
-
-
-
- {t("page-layer-2-networks-more-advanced-link-1")}
-
-
- {t("page-layer-2-networks-more-advanced-link-2")}
-
+
+
+
{t("page-layer-2-networks-more-advanced-title")}
+
+
+ {t("page-layer-2-networks-more-advanced-descripton-1")}{" "}
+
+ {t("page-layer-2-networks-more-advanced-descripton-2")}
+
+
+
{t("page-layer-2-networks-more-advanced-descripton-3")}
+
+
+
+ {t("page-layer-2-networks-more-advanced-link-1")}
+
+
+ {t("page-layer-2-networks-more-advanced-link-2")}
+
+
-
-
+
-
-
-
-
- {t("common:learn-more")}
-
-
-
-
-
-
- {t("common:learn-more")}
-
-
-
-
-
+
+
+
+ {t("common:learn-more")}
+
+
+
+
+
+
+ {t("common:learn-more")}
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/layer-2/networks/page-jsonld.tsx b/app/[locale]/layer-2/networks/page-jsonld.tsx
new file mode 100644
index 00000000000..f246208efb7
--- /dev/null
+++ b/app/[locale]/layer-2/networks/page-jsonld.tsx
@@ -0,0 +1,134 @@
+import { getTranslations } from "next-intl/server"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function Layer2NetworksPageJsonLD({
+ locale,
+ layer2Data,
+ contributors,
+}) {
+ const t = await getTranslations({
+ namespace: "page-layer-2-networks",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/layer-2/networks/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Layer 2 Networks page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-layer-2-networks-meta-title"),
+ description: t("page-layer-2-networks-hero-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: "Layer 2",
+ item: normalizeUrlForJsonLd(locale, "/layer-2/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 3,
+ name: t("page-layer-2-networks-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for Layer 2 Networks listing
+ const networksItemListJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "ItemList",
+ name: t("page-layer-2-networks-meta-title"),
+ description: t("page-layer-2-networks-hero-description"),
+ numberOfItems: layer2Data.length,
+ itemListElement: layer2Data.map((network, index) => ({
+ "@type": "ListItem",
+ position: index + 1,
+ item: {
+ "@type": "SoftwareApplication",
+ name: network.name,
+ description:
+ network.description || `${network.name} Layer 2 network on Ethereum`,
+ url: network.website,
+ applicationCategory: "Blockchain Network",
+ operatingSystem: "Ethereum",
+ additionalProperty: [
+ {
+ "@type": "PropertyValue",
+ name: "Network Type",
+ value: network.rollupType || "Layer 2",
+ },
+ {
+ "@type": "PropertyValue",
+ name: "Maturity Level",
+ value: network.networkMaturity,
+ },
+ {
+ "@type": "PropertyValue",
+ name: "Total Value Locked (TVL)",
+ value: network.tvl ? `$${network.tvl.toLocaleString()}` : "N/A",
+ },
+ {
+ "@type": "PropertyValue",
+ name: "Daily Transaction Cost",
+ value: network.txCosts ? `$${network.txCosts.toFixed(2)}` : "N/A",
+ },
+ {
+ "@type": "PropertyValue",
+ name: "Supported Wallets",
+ value: network.walletsSupportedCount || "N/A",
+ },
+ ],
+ },
+ })),
+ }
+
+ return
+}
diff --git a/app/[locale]/layer-2/networks/page.tsx b/app/[locale]/layer-2/networks/page.tsx
index d1773b85262..b8a08d4b99c 100644
--- a/app/[locale]/layer-2/networks/page.tsx
+++ b/app/[locale]/layer-2/networks/page.tsx
@@ -5,10 +5,11 @@ import {
setRequestLocale,
} from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import I18nProvider from "@/components/I18nProvider"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { dataLoader } from "@/lib/utils/data/dataLoader"
import { getMetadata } from "@/lib/utils/metadata"
import { networkMaturity } from "@/lib/utils/networkMaturity"
@@ -20,6 +21,7 @@ import { walletsData } from "@/data/wallets/wallet-data"
import { BASE_TIME_UNIT } from "@/lib/constants"
import Layer2Networks from "./_components/networks"
+import Layer2NetworksPageJsonLD from "./page-jsonld"
import { fetchEthereumMarketcap } from "@/lib/api/fetchEthereumMarketcap"
import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie"
@@ -118,8 +120,20 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
},
}
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "layer-2/networks",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
+
)
diff --git a/app/[locale]/layer-2/page-jsonld.tsx b/app/[locale]/layer-2/page-jsonld.tsx
new file mode 100644
index 00000000000..0a081f83cc9
--- /dev/null
+++ b/app/[locale]/layer-2/page-jsonld.tsx
@@ -0,0 +1,152 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function Layer2PageJsonLD({
+ locale,
+ contributors,
+}: {
+ locale: Lang | undefined
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-layer-2",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/layer-2/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Layer 2 page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-layer-2-meta-title"),
+ description: t("page-layer-2-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-layer-2-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the article content about Layer 2
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-layer-2-hero-title"),
+ description: t("page-layer-2-meta-description"),
+ image: "https://ethereum.org/images/layer-2/learn-hero.png", // TODO: adjust value when the old theme breakpoints are removed (src/theme.ts)
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ contributor: contributorList,
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for FAQ section
+ const faqJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "FAQPage",
+ mainEntity: [
+ {
+ "@type": "Question",
+ name: t("page-layer-2-faq-ExpandableCard-1-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-layer-2-faq-ExpandableCard-1-description-1")} ${t("page-layer-2-faq-ExpandableCard-1-description-2")}`,
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-layer-2-faq-ExpandableCard-2-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-layer-2-faq-ExpandableCard-2-description-1")} ${t("page-layer-2-faq-ExpandableCard-2-description-2")}`,
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-layer-2-faq-ExpandableCard-3-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-layer-2-faq-ExpandableCard-3-description"),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-layer-2-faq-ExpandableCard-4-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-layer-2-faq-ExpandableCard-4-description"),
+ },
+ },
+ ],
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/layer-2/page.tsx b/app/[locale]/layer-2/page.tsx
index fdb27b0f727..5cf28d5d552 100644
--- a/app/[locale]/layer-2/page.tsx
+++ b/app/[locale]/layer-2/page.tsx
@@ -5,10 +5,11 @@ import {
setRequestLocale,
} from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import I18nProvider from "@/components/I18nProvider"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { dataLoader } from "@/lib/utils/data/dataLoader"
import { getMetadata } from "@/lib/utils/metadata"
import { networkMaturity } from "@/lib/utils/networkMaturity"
@@ -19,6 +20,7 @@ import { layer2Data } from "@/data/networks/networks"
import { BASE_TIME_UNIT } from "@/lib/constants"
import Layer2Page from "./_components/layer-2"
+import Layer2PageJsonLD from "./page-jsonld"
import { routing } from "@/i18n/routing"
import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie"
@@ -67,8 +69,16 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const requiredNamespaces = getRequiredNamespacesForPage("/layer-2")
const messages = pick(allMessages, requiredNamespaces)
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "layer-2",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
+
({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Learn page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-learn-meta-title"),
+ description: t("hero-subtitle"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-learn-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ return
+}
diff --git a/app/[locale]/learn/page.tsx b/app/[locale]/learn/page.tsx
index d7d8ca5c7e3..702b0b7e24b 100644
--- a/app/[locale]/learn/page.tsx
+++ b/app/[locale]/learn/page.tsx
@@ -24,6 +24,8 @@ import { ListItem, UnorderedList } from "@/components/ui/list"
import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
+import LearnPageJsonLD from "./page-jsonld"
+
import developersEthBlocks from "@/public/images/developers-eth-blocks.png"
import dogeComputer from "@/public/images/doge-computer.png"
import enterprise from "@/public/images/enterprise-eth.png"
@@ -177,539 +179,558 @@ export default async function Page({ params }: { params: Promise }) {
}
return (
-
-
-
-
-
-
-
-
-
-
-
- <>
-
-
-
-
- {t("what-is-ethereum-card-title")}
-
- >
-
-
- <>
-
-
-
-
- {t("what-is-eth-card-title")}
-
- >
-
-
- <>
-
-
-
-
- {t("what-is-web3-card-title")}
-
- >
-
-
-
-
-
-
-
-
-
- <>
-
-
-
-
- {t("what-is-a-wallet-card-title")}
-
- >
-
-
- <>
-
-
-
-
- {t("find-a-wallet-button")}
-
- >
-
-
- <>
-
-
-
-
- {t("ethereum-networks-card-button")}
-
- >
-
-
-
-
-
- {t("things-to-consider-banner-title")}
-
- {t("things-to-consider-banner-1")}
-
- {t("things-to-consider-banner-2")}{" "}
-
- {t("things-to-consider-banner-layer-2")}
-
- .
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <>
-
-
-
-
- {t("defi-card-button")}
-
- >
-
-
- <>
-
-
-
-
- {t("stablecoins-card-button")}
-
- >
-
-
- <>
-
-
-
- {t("nft-card-button")}
- >
-
-
- <>
-
-
-
- {t("dao-card-button")}
- >
-
-
- <>
-
-
-
-
- {t("dapp-card-button")}
-
- >
-
-
-
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <>
+
+
+
+
+ {t("what-is-ethereum-card-title")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("what-is-eth-card-title")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("what-is-web3-card-title")}
+
+ >
+
+
+
+
+
+
+
+
+
+ <>
+
+
+
+
+ {t("what-is-a-wallet-card-title")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("find-a-wallet-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("ethereum-networks-card-button")}
+
+ >
+
+
+
+
+
+ {t("things-to-consider-banner-title")}
+ {t("things-to-consider-banner-1")}
-
- {tCommon("decentralized-identity")}
-
-
-
-
- {tCommon("decentralized-social-networks")}
-
-
-
-
- {tCommon("decentralized-science")}
-
-
-
-
- {t("play-to-earn")}
-
-
-
-
- {t("fundraising-through-quadratic-funding")}
+ {t("things-to-consider-banner-2")}{" "}
+
+ {t("things-to-consider-banner-layer-2")}
+ .
-
-
- {t("supply-chain-management")}
-
-
-
-
-
-
-
-
-
- <>
-
-
-
-
- {t("staking-ethereum-card-button")}
-
- >
-
-
- <>
-
-
-
-
- {t("run-a-node-card-title")}
-
- >
-
-
-
-
-
-
-
- <>
-
-
-
-
- {t("energy-consumption-card-button")}
-
- >
-
-
- <>
-
-
-
-
- {t("ethereum-upgrades-card-button")}
-
- >
-
-
- <>
-
-
-
-
- {t("ethereum-whitepaper-card-button")}
-
- >
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ <>
+
+
+
+
+ {t("defi-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("stablecoins-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("nft-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("dao-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("dapp-card-button")}
+
+ >
+
+
+
+
+
+
+ {tCommon("decentralized-identity")}
+
+
+
+
+ {tCommon("decentralized-social-networks")}
+
+
+
+
+ {tCommon("decentralized-science")}
+
+
+
+
+ {t("play-to-earn")}
+
+
+
+
+ {t("fundraising-through-quadratic-funding")}
+
+
+
+
+ {t("supply-chain-management")}
+
+
+
+
+
+
+
+
+
+
+
+ <>
+
+
+
+
+ {t("staking-ethereum-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("run-a-node-card-title")}
+
+ >
+
+
+
+
+
+
+
+ <>
+
+
+
+
+ {t("energy-consumption-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("ethereum-upgrades-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("ethereum-whitepaper-card-button")}
+
+ >
+
+
+
+
+
+
+
+
+
+ <>
+
+
+
+
+ {t("community-hub-card-button")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("get-involved-card-title")}
+
+ >
+
+
+ <>
+
+
+
+
+ {t("online-communities-card-button")}
+
+ >
+
+
+
+
+
+
+ {t("books-about-ethereum")}
+
+
+
+ {t("cryptopians-title")}
+ {" "}
+ {t("cryptopians-description")}
+
+
+
+ {t("out-of-the-ether-title")}
+ {" "}
+ {t("out-of-the-ether-description")}
+
+
+
+ {t("the-infinite-machine-title")}
+ {" "}
+ {t("the-infinite-machine-description")}
+
+
+
+ {t("mastering-ethereum-title")}
+ {" "}
+ {t("mastering-ethereum-description")}
+
+
+
+ {t("proof-of-stake-title")}
+ {" "}
+ {t("proof-of-stake-description")}
+
+
+ {t("podcasts-about-ethereum")}
+
+
+
+ {t("green-pill-title")}
+ {" "}
+ {t("green-pill-description")}
+
+
+
+ {t("zeroknowledge-title")}
+ {" "}
+ {t("zeroknowledge-description")}
+
+
+
+ {t("unchained-title")}
+ {" "}
+ {t("unchained-description")}
+
+
+
+ {t("the-daily-gwei-title")}
+ {" "}
+ {t("the-daily-gwei-description")}
+
+
+
+ {t("bankless-title")}
+ {" "}
+ {t("bankless-description")}
+
+
+ {t("about-ethereum-video-series")}
+
+
+
+ {t("ethereum-basics-title")}
+ {" "}
+ {t("ethereum-basics-description")}
+
+
+
+
+
+
-
-
-
-
-
- <>
-
-
-
-
- {t("community-hub-card-button")}
-
- >
-
-
- <>
-
-
-
-
- {t("get-involved-card-title")}
-
- >
-
-
- <>
-
-
-
-
- {t("online-communities-card-button")}
-
- >
-
-
-
-
-
-
- {t("books-about-ethereum")}
-
-
-
- {t("cryptopians-title")}
- {" "}
- {t("cryptopians-description")}
-
-
-
- {t("out-of-the-ether-title")}
- {" "}
- {t("out-of-the-ether-description")}
-
-
-
- {t("the-infinite-machine-title")}
- {" "}
- {t("the-infinite-machine-description")}
-
-
-
- {t("mastering-ethereum-title")}
- {" "}
- {t("mastering-ethereum-description")}
-
-
-
- {t("proof-of-stake-title")}
- {" "}
- {t("proof-of-stake-description")}
-
-
- {t("podcasts-about-ethereum")}
-
-
-
- {t("green-pill-title")}
- {" "}
- {t("green-pill-description")}
-
-
-
- {t("zeroknowledge-title")}
- {" "}
- {t("zeroknowledge-description")}
-
-
-
- {t("unchained-title")}
- {" "}
- {t("unchained-description")}
-
-
-
- {t("the-daily-gwei-title")}
- {" "}
- {t("the-daily-gwei-description")}
-
-
-
- {t("bankless-title")}
- {" "}
- {t("bankless-description")}
-
-
- {t("about-ethereum-video-series")}
-
-
-
- {t("ethereum-basics-title")}
- {" "}
- {t("ethereum-basics-description")}
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/page-jsonld.tsx b/app/[locale]/page-jsonld.tsx
new file mode 100644
index 00000000000..bbc94dd42af
--- /dev/null
+++ b/app/[locale]/page-jsonld.tsx
@@ -0,0 +1,89 @@
+import { getTranslations } from "next-intl/server"
+
+import { Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function IndexPageJsonLD({
+ locale,
+}: {
+ locale: Lang | undefined
+}) {
+ const t = await getTranslations({
+ namespace: "page-index",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/`)
+
+ // JSON-LD structured data for the homepage
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-index-meta-title"),
+ description: t("page-index-meta-description"),
+ url: url,
+ inLanguage: locale,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ isPartOf: {
+ "@type": "WebSite",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for ethereum.org as an organization
+ const organizationJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Organization",
+ "@id": "https://ethereum.org",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: "https://ethereum.org/images/eth-org-logo.png",
+ description: t("page-index-meta-description"),
+ sameAs: [
+ "https://github.com/ethereum/ethereum-org-website",
+ "https://discord.gg/ethereum-org",
+ "https://x.com/EthDotOrg",
+ ],
+ mainEntityOfPage: `https://ethereum.org`,
+ foundingDate: "2014",
+ slogan:
+ "Ethereum is the community-run technology powering the cryptocurrency ether and thousands of decentralized applications",
+ }
+
+ return
+}
diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx
index 9682aefefac..cd7c8edc14b 100644
--- a/app/[locale]/page.tsx
+++ b/app/[locale]/page.tsx
@@ -80,6 +80,7 @@ import {
RSS_DISPLAY_COUNT,
} from "@/lib/constants"
+import IndexPageJsonLD from "./page-jsonld"
import { getActivity, getUpcomingEvents } from "./utils"
import { routing } from "@/i18n/routing"
@@ -424,536 +425,547 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
blogLinks.push(...BLOGS_WITHOUT_FEED)
return (
-
-
-
-
- {subHeroCTAs.map(
- ({ label, description, href, className, Svg }, idx) => {
- const Link = (
- props: Omit<
- SvgButtonLinkProps,
- "Svg" | "href" | "label" | "children"
- >
- ) => (
-
- {description}
-
- )
- return (
-
-
-
-
- )
- }
- )}
-
+ <>
+
+
+
+
+
+ {subHeroCTAs.map(
+ ({ label, description, href, className, Svg }, idx) => {
+ const Link = (
+ props: Omit<
+ SvgButtonLinkProps,
+ "Svg" | "href" | "label" | "children"
+ >
+ ) => (
+
+ {description}
+
+ )
+ return (
+
+
+
+
+ )
+ }
+ )}
+
- {/* Use Cases - A new way to use the internet */}
-
-
-
- {t("page-index-use-cases-tag")}
+
+
+ {t("page-index-use-cases-tag")}
+
+
+ {t("page-index-bento-header")}
+
-
- {t("page-index-bento-header")}
-
-
- {/* Mobile - dynamic / lazy loaded */}
-
-
- {/* Desktop */}
- {bentoItems.map(({ className, ...item }) => (
-
- ))}
-
-
- {/* Activity - The strongest ecosystem */}
-
-
-
-
-
-
- {t("page-index-activity-tag")}
- {t("page-index-activity-header")}
-
-
- {t("page-index-activity-description")}
-
-
-
-
- {t("page-index-activity-action-primary")}
-
-
- {t("page-index-activity-action")}
-
-
-
-
-
-
- {/* Learn - Understand Ethereum */}
-
-
-
-
-
-
- {t("page-index-learn-tag")}
- {t("page-index-learn-header")}
-
-
{t("page-index-learn-description")}
-
-
- {t("page-index-popular-topics-header")}
-
-
- {popularTopics.map(
- ({ label, Svg, href, eventName, className }) => (
-
:first-child]:flex-row",
- className
- )}
- customEventOptions={{
- eventCategory,
- eventAction: "popular topics",
- eventName,
- }}
- >
-
- {label}
-
-
- )
- )}
-
-
+ {/* Desktop */}
+ {bentoItems.map(({ className, ...item }) => (
+
+ ))}
+
+
+ {/* Activity - The strongest ecosystem */}
+
+
+
+
+
+
+ {t("page-index-activity-tag")}
+ {t("page-index-activity-header")}
+
+
+ {t("page-index-activity-description")}
+
+
+
+
+ {t("page-index-activity-action-primary")}
+
+
- {t("page-index-popular-topics-action")}
+ {t("page-index-activity-action")}
- {" "}
-
-
-
- {/* Values - The Internet Is Changing */}
-
-
- {t("page-index-values-tag")}
- {t("page-index-values-header")}
-
- {t("page-index-values-description")}
-
-
-
- {/* dynamic / lazy loaded */}
-
-
-
-
-
- {/* Builders - Blockchain's biggest builder community */}
-
-
-
-
-
-
- {t("page-index-builders-tag")}
- {t("page-index-builders-header")}
- {t("page-index-builders-description")}
-
-
- {t("page-index-builders-action-primary")}
-
-
- {t("page-index-builders-action-secondary")}
-
-
-
- {/* CLIENT SIDE */}
-
+
+
+ {/* Learn - Understand Ethereum */}
+
+
+
+
+
+
+ {t("page-index-learn-tag")}
+ {t("page-index-learn-header")}
+
+
{t("page-index-learn-description")}
+
+
+ {t("page-index-popular-topics-header")}
+
+
+ {popularTopics.map(
+ ({ label, Svg, href, eventName, className }) => (
+
:first-child]:flex-row",
+ className
+ )}
+ customEventOptions={{
+ eventCategory,
+ eventAction: "popular topics",
+ eventName,
+ }}
+ >
+
+ {label}
+
+
+ )
+ )}
+
+
+
+ {t("page-index-popular-topics-action")}
+
+
+
+
{" "}
+
+
+
+ {/* Values - The Internet Is Changing */}
+
+
+ {t("page-index-values-tag")}
+ {t("page-index-values-header")}
+
+ {t("page-index-values-description")}
+
+
+
+ {/* dynamic / lazy loaded */}
+
+
-
-
-
-
- {/* Ethereum.org community - Built by the community */}
-
+
+ {/* Events */}
+
+
+ {t("page-index-events-header")}
+
+ {t("page-index-events-subtitle")}
+
+
+ {upcomingEvents.map(
+ (
+ {
+ title,
+ href,
+ location,
+ description,
+ startDate,
+ endDate,
+ imageUrl,
+ },
+ idx
+ ) => (
+
+
+ {imageUrl ? (
+
+ ) : (
+
+ )}
+
+
+
+ {title}
+
+ {(isValidDate(startDate) || isValidDate(endDate)) &&
+ new Intl.DateTimeFormat(locale, {
+ month: "long",
+ day: "numeric",
+ year: "numeric",
+ }).formatRange(
+ new Date(
+ isValidDate(startDate) ? startDate : endDate
+ ),
+ new Date(
+ isValidDate(endDate) ? endDate : startDate
+ )
+ )}
+
+ {location}
+
+
+ )
+ )}
+
+
+
+
+ {t("page-index-events-action")}
+
+
+
+
+ {/* Join ethereum.org */}
+
+
+
+
{t("page-index-join-header")}
+
{t("page-index-join-description")}
+
+
+ {joinActions.map(
+ ({ Svg, label, href, className, description, eventName }) => (
+
+ {description}
+
+ )
+ )}
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/quizzes/_components/quizzes.tsx b/app/[locale]/quizzes/_components/quizzes.tsx
index 7992d6e8fbc..1912cd98a3e 100644
--- a/app/[locale]/quizzes/_components/quizzes.tsx
+++ b/app/[locale]/quizzes/_components/quizzes.tsx
@@ -51,73 +51,75 @@ const QuizzesPage = () => {
)
return (
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
{t("want-more-quizzes")}
+
{t("contribute")}
+
+
+
+
+ {t("add-quiz")}
+
+
+
+
+
+
-
-
-
{t("want-more-quizzes")}
-
{t("contribute")}
-
-
-
-
- {t("add-quiz")}
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/quizzes/page-jsonld.tsx b/app/[locale]/quizzes/page-jsonld.tsx
new file mode 100644
index 00000000000..308f644ed14
--- /dev/null
+++ b/app/[locale]/quizzes/page-jsonld.tsx
@@ -0,0 +1,79 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function QuizzesPageJsonLD({
+ locale,
+ contributors,
+}: {
+ locale: Lang | undefined
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-quizzes",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/quizzes/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Quizzes page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("common:quizzes-title"),
+ description: t("quizzes-subtitle"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("common:quizzes-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ return
+}
diff --git a/app/[locale]/quizzes/page.tsx b/app/[locale]/quizzes/page.tsx
index 88db4cc27a3..cee67c69a28 100644
--- a/app/[locale]/quizzes/page.tsx
+++ b/app/[locale]/quizzes/page.tsx
@@ -5,14 +5,16 @@ import {
setRequestLocale,
} from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import I18nProvider from "@/components/I18nProvider"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import QuizzesPage from "./_components/quizzes"
+import QuizzesPageJsonLD from "./page-jsonld"
const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const { locale } = await params
@@ -24,8 +26,16 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const requiredNamespaces = getRequiredNamespacesForPage("/quizzes")
const messages = pick(allMessages, requiredNamespaces)
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "quizzes",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
+
)
diff --git a/app/[locale]/resources/page-jsonld.tsx b/app/[locale]/resources/page-jsonld.tsx
new file mode 100644
index 00000000000..35794ae91e0
--- /dev/null
+++ b/app/[locale]/resources/page-jsonld.tsx
@@ -0,0 +1,79 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function ResourcesPageJsonLD({
+ locale,
+ contributors,
+}: {
+ locale: Lang | undefined
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-resources",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/resources/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Resources page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-resources-meta-title"),
+ description: t("page-resources-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-resources-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ return
+}
diff --git a/app/[locale]/resources/page.tsx b/app/[locale]/resources/page.tsx
index a38876f7173..de7f85facd3 100644
--- a/app/[locale]/resources/page.tsx
+++ b/app/[locale]/resources/page.tsx
@@ -1,6 +1,6 @@
import { getTranslations } from "next-intl/server"
-import type { Lang } from "@/lib/types"
+import type { CommitHistory, Lang } from "@/lib/types"
import BannerNotification from "@/components/Banners/BannerNotification"
import { HubHero } from "@/components/Hero"
@@ -15,6 +15,7 @@ import { Section } from "@/components/ui/section"
import TabNav, { StickyContainer } from "@/components/ui/TabNav"
import { cn } from "@/lib/utils/cn"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { dataLoader } from "@/lib/utils/data/dataLoader"
import { getMetadata } from "@/lib/utils/metadata"
@@ -22,6 +23,7 @@ import { GITHUB_REPO_URL } from "@/lib/constants"
import { BASE_TIME_UNIT } from "@/lib/constants"
import { ResourceItem, ResourcesContainer } from "./_components/ResourcesUI"
+import ResourcesPageJsonLD from "./page-jsonld"
import { getResources } from "./utils"
import { fetchGrowThePie } from "@/lib/api/fetchGrowThePie"
@@ -47,156 +49,167 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const resourceSections = await getResources({ txCostsMedianUsd })
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "resources",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
-
-
- {t("page-resources-banner-notification-message")}{" "}
-
- {t("page-resources-share-feedback")}
-
-
-
-
-
-
-
-
- {t("page-resources-whats-on-this-page")}
-
-
+
+
+
+
+ {t("page-resources-banner-notification-message")}{" "}
+
-
-
- {resourceSections.map(({ key, icon, label, boxes }) => (
-
-
-
-
- {icon ||
}
+ >
+ {t("page-resources-share-feedback")}
+
+
+
+
+
+
+
+
+ {t("page-resources-whats-on-this-page")}
+
+
+
+
+ {resourceSections.map(({ key, icon, label, boxes }) => (
+
+
+
+
+ {icon || }
+
+
{label}
- {label}
-
-
- {boxes.map(({ title, metric, items, className }) => (
-
-
- {title}
-
-
- {metric && metric}
-
- {items.map(({ className, ...item }) => (
-
- ))}
-
+
+ {boxes.map(({ title, metric, items, className }) => (
+
+
+ {title}
+
+
+ {metric && metric}
+
+ {items.map(({ className, ...item }) => (
+
+ ))}
+
+
-
- ))}
-
-
-
- ))}
-
+ ))}
+
+
+
+ ))}
+
+
+
+
+
+
+
+ ethereumdashboards.com
+
+
-
-
-
-
-
- ethereumdashboards.com
-
-
-
-
-
-
-
-
{t("page-resources-contribute-title")}
-
- {t("page-resources-contribute-description")}
-
-
-
- {/* TODO: Add issue template for resource listing and redirect to new template */}
-
- {t("page-resources-suggest-resource")}
-
-
- {t("page-resources-found-bug")}
-
-
-
-
-
-
-
+
+
+
+
{t("page-resources-contribute-title")}
+
+ {t("page-resources-contribute-description")}
+
+
+
+ {/* TODO: Add issue template for resource listing and redirect to new template */}
+
+ {t("page-resources-suggest-resource")}
+
+
+ {t("page-resources-found-bug")}
+
+
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/roadmap/_components/roadmap.tsx b/app/[locale]/roadmap/_components/roadmap.tsx
index 61cfaeff444..736407daaa0 100644
--- a/app/[locale]/roadmap/_components/roadmap.tsx
+++ b/app/[locale]/roadmap/_components/roadmap.tsx
@@ -107,160 +107,162 @@ const RoadmapPage = () => {
// TODO: MATOMO EVENTS
return (
-
-
- {t("page-roadmap-banner-notification")}
-
-
-
+ <>
+
+
+ {t("page-roadmap-banner-notification")}
+
+
+
-
-
-
-
-
-
{t("page-roadmap-changes-coming-title")}
-
- {t("page-roadmap-changes-coming-description")}
-
-
- {changesComingItems.map((item) => (
-
-
-
{item.title}
-
- {item.icon}
-
-
-
{item.description}
-
- {item.button.label}
-
-
- ))}
+
+
-
-
-
-
{t("page-roadmap-why-need-title")}
-
{t("page-roadmap-why-need-description")}
-
{t("page-roadmap-how-defined-title")}
-
{t("page-roadmap-how-defined-p1")}
-
-
+
+
{t("page-roadmap-changes-coming-title")}
+
+ {t("page-roadmap-changes-coming-description")}
-
-
-
-
- {t("page-roadmap-governance-button")}
-
-
-
-
+
+ {changesComingItems.map((item) => (
+
+
+
{item.title}
+
+ {item.icon}
+
+
+
{item.description}
+
+ {item.button.label}
+
+
+ ))}
+
-
-
-
- {t("page-roadmap-technical-upgrades-title")}
-
-
- {technicalUpgradesItems.map((item) => (
-
+
+
{t("page-roadmap-why-need-title")}
+
{t("page-roadmap-why-need-description")}
+
{t("page-roadmap-how-defined-title")}
+
{t("page-roadmap-how-defined-p1")}
+
+
+
+
+
+
+
+ {t("page-roadmap-governance-button")}
+
+
+
+
- ))}
+
-
-
-
-
+
+
+ {t("page-roadmap-technical-upgrades-title")}
+
+
+ {technicalUpgradesItems.map((item) => (
+
+ ))}
+
-
-
{t("page-roadmap-timeline-title")}
-
-
-
-
- {t("page-roadmap-faq-1-p1")}{" "}
- {t("page-roadmap-faq-1-p1-continued")}
-
-
{t("page-roadmap-faq-1-p2")}
-
-
-
-
-
- {t("page-roadmap-faq-2-p1")}{" "}
- {t("page-roadmap-faq-2-p1-strong")}{" "}
- {t("page-roadmap-faq-2-p1-continued")}
-
-
{t("page-roadmap-faq-2-p2")}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
{t("page-roadmap-timeline-title")}
+
+
+
+
+ {t("page-roadmap-faq-1-p1")}{" "}
+ {t("page-roadmap-faq-1-p1-continued")}
+
+
{t("page-roadmap-faq-1-p2")}
+
+
+
+
+
+ {t("page-roadmap-faq-2-p1")}{" "}
+ {t("page-roadmap-faq-2-p1-strong")}{" "}
+ {t("page-roadmap-faq-2-p1-continued")}
+
+
{t("page-roadmap-faq-2-p2")}
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+ >
)
}
diff --git a/app/[locale]/roadmap/page-jsonld.tsx b/app/[locale]/roadmap/page-jsonld.tsx
new file mode 100644
index 00000000000..9546d4712a5
--- /dev/null
+++ b/app/[locale]/roadmap/page-jsonld.tsx
@@ -0,0 +1,164 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function RoadmapPageJsonLD({
+ locale,
+ contributors,
+}: {
+ locale: Lang | undefined
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-roadmap",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/roadmap/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Roadmap page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-roadmap-meta-title"),
+ description: t("page-roadmap-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-roadmap-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the roadmap article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-roadmap-title"),
+ description: t("page-roadmap-meta-description"),
+ image: "https://ethereum.org/images/heroes/roadmap-hub-hero.jpg",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ contributor: contributorList,
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Roadmap",
+ description:
+ "The future development and upgrade path of the Ethereum blockchain",
+ },
+ }
+
+ // JSON-LD for the FAQ section
+ const faqJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "FAQPage",
+ mainEntity: [
+ {
+ "@type": "Question",
+ name: t("page-roadmap-faq-1-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-roadmap-faq-1-p1")} ${t("page-roadmap-faq-1-p1-continued")} ${t("page-roadmap-faq-1-p2")}`.replace(
+ /<[^>]*>/g,
+ ""
+ ),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-roadmap-faq-2-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-roadmap-faq-2-p1")} ${t("page-roadmap-faq-2-p1-strong")} ${t("page-roadmap-faq-2-p1-continued")} ${t("page-roadmap-faq-2-p2")}`.replace(
+ /<[^>]*>/g,
+ ""
+ ),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-roadmap-faq-3-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-roadmap-faq-3-p1").replace(/<[^>]*>/g, ""),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-roadmap-faq-4-title"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-roadmap-faq-4-p1").replace(/<[^>]*>/g, ""),
+ },
+ },
+ ],
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/roadmap/page.tsx b/app/[locale]/roadmap/page.tsx
index 7bc113e023a..dfa58557424 100644
--- a/app/[locale]/roadmap/page.tsx
+++ b/app/[locale]/roadmap/page.tsx
@@ -1,14 +1,16 @@
import { pick } from "lodash"
import { getTranslations } from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import I18nProvider from "@/components/I18nProvider"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import RoadmapPage from "./_components/roadmap"
+import RoadmapPageJsonLD from "./page-jsonld"
import { loadMessages } from "@/i18n/loadMessages"
@@ -20,8 +22,16 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const requiredNamespaces = getRequiredNamespacesForPage("/roadmap")
const messages = pick(allMessages, requiredNamespaces)
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "roadmap",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
+
)
diff --git a/app/[locale]/roadmap/vision/_components/vision.tsx b/app/[locale]/roadmap/vision/_components/vision.tsx
index 8c2a745772f..3c4077e4742 100644
--- a/app/[locale]/roadmap/vision/_components/vision.tsx
+++ b/app/[locale]/roadmap/vision/_components/vision.tsx
@@ -120,139 +120,141 @@ const VisionPage = ({
}
return (
-
-
-
-
-
-
- {t("page-roadmap-vision-upgrade-needs")}
- {t("page-roadmap-vision-upgrade-needs-desc")}
- {t("page-roadmap-vision-upgrade-needs-desc-2")}
- {t("page-roadmap-vision-upgrade-needs-desc-3")}
-
-
-
- {t("page-roadmap-vision-2022")}
+ <>
+
+
+
+
+
+
+ {t("page-roadmap-vision-upgrade-needs")}
+ {t("page-roadmap-vision-upgrade-needs-desc")}
+ {t("page-roadmap-vision-upgrade-needs-desc-2")}
+ {t("page-roadmap-vision-upgrade-needs-desc-3")}
+
+
+
+ {t("page-roadmap-vision-2022")}
+
+
+
+
+ {t("page-roadmap-vision-2021-updates")}
+
+
+
+
+ {t("page-roadmap-vision-2021")}
+
+
+
+
+ {t("page-roadmap-vision-upgrade-needs-serenity")}
+
+
+
+
+ {t("page-roadmap-vision-2014")}
+
+
+
+ {t("page-roadmap-vision-upgrade-needs-desc-5")}
+ {t("page-roadmap-vision-upgrade-needs-desc-6")}
+
+
+
+
+ {t("page-roadmap-vision-problems")}
+
+ {paths.map((path, idx) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ {t("page-roadmap-vision-understanding")}
+
+ {t("page-roadmap-vision-scalability")}
+
+ {t("page-roadmap-vision-scalability-desc")}
+ {t("page-roadmap-vision-scalability-desc-3")}
+
+ {t("page-roadmap-vision-scalability-desc-4")}{" "}
+
+ {t("page-roadmap-vision-danksharding")}
+ {" "}
+
+
+ {t("page-roadmap-vision-security")}
+
+ {t("page-roadmap-vision-security-desc")}
+
+ {t("page-roadmap-vision-security-desc-3")}{" "}
+
+ {t("page-upgrades-index:page-upgrades-proof-stake-link")}
+ {" "}
+
+
+ {t("page-roadmap-vision-security-desc-5")}{" "}
+
+ {t("page-roadmap-vision-security-desc-5-link")}
-
-
-
- {t("page-roadmap-vision-2021-updates")}
+
+ {t("page-roadmap-vision-security-desc-10")}
+
+ {t("page-roadmap-vision-security-validator")}{" "}
+
+ {t("page-roadmap-vision-ethereum-node")}
-
-
-
- {t("page-roadmap-vision-2021")}
-
-
-
-
- {t("page-roadmap-vision-upgrade-needs-serenity")}
+
+
+ {t("page-roadmap-vision-security-staking")}
+
+
+ {t("page-roadmap-vision-sustainability")}{" "}
+
+
+ {t("page-roadmap-vision-sustainability-subtitle")}
+
+ {t("page-roadmap-vision-sustainability-desc-1")}{" "}
+
+ {t("page-roadmap-vision-mining")}
-
-
-
- {t("page-roadmap-vision-2014")}
+
+
+ {t("page-roadmap-vision-sustainability-desc-2")}{" "}
+
+ {t("page-roadmap-vision-staking-lower")}
-
-
- {t("page-roadmap-vision-upgrade-needs-desc-5")}
- {t("page-roadmap-vision-upgrade-needs-desc-6")}
-
-
-
-
- {t("page-roadmap-vision-problems")}
-
- {paths.map((path, idx) => (
-
- ))}
-
-
-
-
-
-
-
-
- {t("page-roadmap-vision-understanding")}
-
- {t("page-roadmap-vision-scalability")}
-
- {t("page-roadmap-vision-scalability-desc")}
- {t("page-roadmap-vision-scalability-desc-3")}
-
- {t("page-roadmap-vision-scalability-desc-4")}{" "}
-
- {t("page-roadmap-vision-danksharding")}
- {" "}
-
-
- {t("page-roadmap-vision-security")}
-
- {t("page-roadmap-vision-security-desc")}
-
- {t("page-roadmap-vision-security-desc-3")}{" "}
-
- {t("page-upgrades-index:page-upgrades-proof-stake-link")}
- {" "}
-
-
- {t("page-roadmap-vision-security-desc-5")}{" "}
-
- {t("page-roadmap-vision-security-desc-5-link")}
-
-
- {t("page-roadmap-vision-security-desc-10")}
-
- {t("page-roadmap-vision-security-validator")}{" "}
-
- {t("page-roadmap-vision-ethereum-node")}
-
-
-
- {t("page-roadmap-vision-security-staking")}
-
-
- {t("page-roadmap-vision-sustainability")}{" "}
-
-
- {t("page-roadmap-vision-sustainability-subtitle")}
-
- {t("page-roadmap-vision-sustainability-desc-1")}{" "}
-
- {t("page-roadmap-vision-mining")}
-
-
-
- {t("page-roadmap-vision-sustainability-desc-2")}{" "}
-
- {t("page-roadmap-vision-staking-lower")}
-
-
- {t("page-roadmap-vision-sustainability-desc-3")}
-
- {t("page-roadmap-vision-sustainability-desc-8")}
-
- {t("page-upgrades-index:page-upgrades-merge-btn")}
-
-
-
-
-
-
-
-
+
+
{t("page-roadmap-vision-sustainability-desc-3")}
+
+ {t("page-roadmap-vision-sustainability-desc-8")}
+
+ {t("page-upgrades-index:page-upgrades-merge-btn")}
+
+
+
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/roadmap/vision/page-jsonld.tsx b/app/[locale]/roadmap/vision/page-jsonld.tsx
new file mode 100644
index 00000000000..9a1e8284776
--- /dev/null
+++ b/app/[locale]/roadmap/vision/page-jsonld.tsx
@@ -0,0 +1,125 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function RoadmapVisionPageJsonLD({
+ locale,
+ lastEditLocaleTimestamp,
+ contributors,
+}: {
+ locale: Lang | undefined
+ lastEditLocaleTimestamp: string
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-roadmap-vision",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/roadmap/vision/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Vision page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-roadmap-vision-title"),
+ description: t("page-roadmap-vision-subtitle"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: "Roadmap",
+ item: normalizeUrlForJsonLd(locale, "/roadmap/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 3,
+ name: t("page-roadmap-vision-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the vision article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-roadmap-vision-title"),
+ description: t("page-roadmap-vision-subtitle"),
+ image: "https://ethereum.org/images/upgrades/oldship.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ contributor: contributorList,
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Vision",
+ description:
+ "The vision for Ethereum's future development and capabilities",
+ },
+ dateModified: lastEditLocaleTimestamp,
+ }
+
+ return
+}
diff --git a/app/[locale]/roadmap/vision/page.tsx b/app/[locale]/roadmap/vision/page.tsx
index 3c3a0c798c5..dfce76879f7 100644
--- a/app/[locale]/roadmap/vision/page.tsx
+++ b/app/[locale]/roadmap/vision/page.tsx
@@ -14,6 +14,7 @@ import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import VisionPage from "./_components/vision"
+import RoadmapVisionPageJsonLD from "./page-jsonld"
const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const { locale } = await params
@@ -35,9 +36,15 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
return (
+
)
diff --git a/app/[locale]/run-a-node/_components/run-a-node.tsx b/app/[locale]/run-a-node/_components/run-a-node.tsx
index 15f074f8aed..2cc83990547 100644
--- a/app/[locale]/run-a-node/_components/run-a-node.tsx
+++ b/app/[locale]/run-a-node/_components/run-a-node.tsx
@@ -295,478 +295,488 @@ const RunANodePage = ({
]
return (
-
-
-
-
-
-
-
-
-
- {t("page-run-a-node-what-1-subtitle")}
- {t("page-run-a-node-what-1-text")}
- {t("page-run-a-node-what-2-subtitle")}
- {t("page-run-a-node-what-2-text")}
- {t("page-run-a-node-what-3-subtitle")}
- {t("page-run-a-node-what-3-text")}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{t("page-run-a-node-who-copy-2")}
-
{t("page-run-a-node-who-copy-3")}
-
- {t("page-run-a-node-who-copy-bold")}
-
+ <>
+
+
+
-
-
-
-
-
-
-
-
- {whyRunANodeCards.map(({ Svg, title, preview, body, alt }) => (
- )
- // @ts-expect-error alt does not exist as a valid prop
- alt={alt}
- svg={({ className }) => (
-
- )}
- key={title}
- >
- {body.map((item) => (
- {item}
- ))}
-
- ))}
-
-
-
-
-
-
- {t("page-run-a-node-getting-started-title")}
-
-
-
-
- {t("page-run-a-node-getting-started-software-section-1")}
-
-
-
-
- {t(
- "page-run-a-node-getting-started-software-section-1-alert"
- )}
-
-
-
- {t("page-run-a-node-getting-started-software-section-1-link")}
-
-
-
- )
- // @ts-expect-error alt does not exist as a valid prop
- alt={t("page-run-a-node-glyph-alt-terminal")}
- />
-
-
+
-
-
- )
- // @ts-expect-error alt does not exist as a valid prop
- alt={t("page-run-a-node-glyph-alt-dappnode")}
+
+
+
+
+
+
+ {t("page-run-a-node-what-1-subtitle")}
+ {t("page-run-a-node-what-1-text")}
+ {t("page-run-a-node-what-2-subtitle")}
+ {t("page-run-a-node-what-2-text")}
+ {t("page-run-a-node-what-3-subtitle")}
+ {t("page-run-a-node-what-3-text")}
+
+
+
-
-
-
-
-
-
-
-
-
-
-
- {t("page-run-a-node-getting-started-software-section-3a")}
-
-
-
-
-
-
- )
- // @ts-expect-error alt does not exist as a valid prop
- alt={t("page-run-a-node-glyph-alt-phone")}
+
+
+
+
+
+
+
+
-
-
-
-
-
-
- {t("page-run-a-node-choose-your-adventure-title")}
- {t("page-run-a-node-choose-your-adventure-1")}
- {t("page-run-a-node-choose-your-adventure-2")}
-
-
-
-
-
- {t("page-run-a-node-buy-fully-loaded-title")}
-
-
{t("page-run-a-node-buy-fully-loaded-description")}
-
- - {t("page-run-a-node-buy-fully-loaded-note-1")}
- - {t("page-run-a-node-buy-fully-loaded-note-2")}
- -
-
{t("page-run-a-node-buy-fully-loaded-note-3")}
-
-
+
+
+
+
+
+
+
{t("page-run-a-node-who-copy-2")}
+
{t("page-run-a-node-who-copy-3")}
+
+ {t("page-run-a-node-who-copy-bold")}
+
-
-
- {t("page-run-a-node-shop-dappnode")}
-
-
- {t("page-run-a-node-shop-avado")}
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {whyRunANodeCards.map(({ Svg, title, preview, body, alt }) => (
+ )
+ // @ts-expect-error alt does not exist as a valid prop
+ alt={alt}
+ svg={({ className }) => (
+
+ )}
+ key={title}
+ >
+ {body.map((item) => (
+ {item}
+ ))}
+
+ ))}
+
+
+
+
+
+
+ {t("page-run-a-node-getting-started-title")}
+
+
+
+
+ {t("page-run-a-node-getting-started-software-section-1")}
+
+
+
+
+ {t(
+ "page-run-a-node-getting-started-software-section-1-alert"
+ )}
+
+
+
+ {t("page-run-a-node-getting-started-software-section-1-link")}
+
+
+
+ )
+ // @ts-expect-error alt does not exist as a valid prop
+ alt={t("page-run-a-node-glyph-alt-terminal")}
/>
- {t("page-run-a-node-build-your-own-title")}
-
-
{t("page-run-a-node-choose-your-adventure-build-1")}
-
- -
- {t("page-run-a-node-choose-your-adventure-build-bullet-1")}
-
- -
- {t("page-run-a-node-choose-your-adventure-build-bullet-2")}
-
- -
- {t("page-run-a-node-choose-your-adventure-build-bullet-3")}
-
-
-
-
-
-
-
-
-
- {t("page-run-a-node-build-your-own-title")}
-
-
-
-
- {t("page-run-a-node-build-your-own-hardware-title")}
-
-
-
-
- {t("page-run-a-node-build-your-own-minimum-specs")}
-
- -
- {t("page-run-a-node-build-your-own-min-ram")}
-
-
- {t("page-run-a-node-build-your-own-ram-note-1")}
-
-
-
-
- {t("page-run-a-node-build-your-own-ram-note-2")}
-
-
-
- -
- {t("page-run-a-node-build-your-own-min-ssd")}
-
-
-
- {t("page-run-a-node-build-your-own-ssd-note")}
-
-
-
-
-
-
-
-
- {t("page-run-a-node-build-your-own-recommended")}
-
- -
- {t("page-run-a-node-build-your-own-nuc")}
-
-
- {t("page-run-a-node-build-your-own-nuc-small")}
-
-
-
- -
- {t("page-run-a-node-build-your-own-connection")}
-
-
- {t("page-run-a-node-build-your-own-connection-small")}
-
-
-
- -
- {t("page-run-a-node-build-your-own-peripherals")}
-
-
- {t("page-run-a-node-build-your-own-peripherals-small")}
-
-
-
-
-
-
-
-
-
-
-
- {t("page-run-a-node-build-your-own-software")}
-
+
+
+
+
+
+ )
+ // @ts-expect-error alt does not exist as a valid prop
+ alt={t("page-run-a-node-glyph-alt-dappnode")}
+ />
+
+
+
+
+
+
+
-
-
-
-
- {t("page-run-a-node-build-your-own-software-option-1-title")}
-
+
+
- {t(
- "page-run-a-node-build-your-own-software-option-1-description"
- )}
+ {t("page-run-a-node-getting-started-software-section-3a")}
+
+
+
+
+
+ )
+ // @ts-expect-error alt does not exist as a valid prop
+ alt={t("page-run-a-node-glyph-alt-phone")}
+ />
+
+
+
+
+
+
+ {t("page-run-a-node-choose-your-adventure-title")}
+ {t("page-run-a-node-choose-your-adventure-1")}
+ {t("page-run-a-node-choose-your-adventure-2")}
+
+
+
+
+
+ {t("page-run-a-node-buy-fully-loaded-title")}
+
+
{t("page-run-a-node-buy-fully-loaded-description")}
+
+ - {t("page-run-a-node-buy-fully-loaded-note-1")}
+ - {t("page-run-a-node-buy-fully-loaded-note-2")}
+ -
+
{t("page-run-a-node-buy-fully-loaded-note-3")}
+
+
-
- {t("page-run-a-node-build-your-own-software-option-1-button")}
+
+ {t("page-run-a-node-shop-dappnode")}
+
+
+ {t("page-run-a-node-shop-avado")}
-
+
-
+
-
- {t("page-run-a-node-build-your-own-software-option-2-title")}
-
-
- {t(
- "page-run-a-node-build-your-own-software-option-2-description-1"
- )}
-
+
+
+ {t("page-run-a-node-build-your-own-title")}
+
- {t(
- "page-run-a-node-build-your-own-software-option-2-description-2"
- )}
+ {t("page-run-a-node-choose-your-adventure-build-1")}
+
+ -
+ {t("page-run-a-node-choose-your-adventure-build-bullet-1")}
+
+ -
+ {t("page-run-a-node-choose-your-adventure-build-bullet-2")}
+
+ -
+ {t("page-run-a-node-choose-your-adventure-build-bullet-3")}
+
+
+
+
+
+
+
+
+ {t("page-run-a-node-build-your-own-title")}
+
+
+
+
+ {t("page-run-a-node-build-your-own-hardware-title")}
+
+
+
+
+ {t("page-run-a-node-build-your-own-minimum-specs")}
+
+ -
+ {t("page-run-a-node-build-your-own-min-ram")}
+
+
+ {t("page-run-a-node-build-your-own-ram-note-1")}
+
+
+
+
+ {t("page-run-a-node-build-your-own-ram-note-2")}
+
+
+
+ -
+ {t("page-run-a-node-build-your-own-min-ssd")}
+
+
+
+ {t("page-run-a-node-build-your-own-ssd-note")}
+
+
+
+
+
+
+
+
+ {t("page-run-a-node-build-your-own-recommended")}
+
+ -
+ {t("page-run-a-node-build-your-own-nuc")}
+
+
+ {t("page-run-a-node-build-your-own-nuc-small")}
+
+
+
+ -
+ {t("page-run-a-node-build-your-own-connection")}
+
+
+ {t("page-run-a-node-build-your-own-connection-small")}
+
+
+
+ -
+ {t("page-run-a-node-build-your-own-peripherals")}
+
+
+ {t("page-run-a-node-build-your-own-peripherals-small")}
+
+
+
+
+
+
+
+
+
+
+
+ {t("page-run-a-node-build-your-own-software")}
+
+
+
+
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-1-title"
+ )}
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-1-description"
+ )}
+
+
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-1-button"
+ )}
+
+
+
+
+
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-2-title"
+ )}
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-2-description-1"
+ )}
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-2-description-2"
+ )}
+
+
+
+
+
+ {t(
+ "page-run-a-node-build-your-own-software-option-2-button"
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ {t("page-run-a-node-community-title")}
+ {t("page-run-a-node-community-description-1")}
+ {t("page-run-a-node-community-description-2")}
+
+
+ {t("page-run-a-node-community-link-1")}
+
-
- {t(
- "page-run-a-node-build-your-own-software-option-2-button"
- )}
-
+ {t("page-run-a-node-community-link-2")}
-
-
-
-
-
-
-
-
- {t("page-run-a-node-community-title")}
- {t("page-run-a-node-community-description-1")}
- {t("page-run-a-node-community-description-2")}
-
-
-
- {t("page-run-a-node-community-link-1")}
-
-
- {t("page-run-a-node-community-link-2")}
-
-
-
+
+
+
+
+
+
+
+
+ {t("page-run-a-node-further-reading-title")}
+
+ -
+
+ {t("page-run-a-node-further-reading-1-link")}
+ {" "}
+ - {t("page-run-a-node-further-reading-1-author")}
+
+ -
+
+ {t("page-run-a-node-further-reading-2-link")}
+
+
+ -
+
+ {t("page-run-a-node-further-reading-3-link")}
+ {" "}
+ - {t("page-run-a-node-further-reading-3-author")}
+
+
+
+
+
+
+
-
-
-
-
- {t("page-run-a-node-further-reading-title")}
-
- -
-
- {t("page-run-a-node-further-reading-1-link")}
- {" "}
- - {t("page-run-a-node-further-reading-1-author")}
-
- -
-
- {t("page-run-a-node-further-reading-2-link")}
+
+
{t("page-run-a-node-staking-title")}
+ {t("page-run-a-node-staking-description")}
+
+
+ {t("page-run-a-node-staking-link")}
+
+
+
+
+
+
+
+ {t("page-run-a-node-staking-plans-title")}
+
+
+
+
+
+ {t("page-run-a-node-staking-plans-ethstaker-link-description")} -{" "}
+
+ {t("page-run-a-node-staking-plans-ethstaker-link-label")}
-
-
-
- {t("page-run-a-node-further-reading-3-link")}
- {" "}
- - {t("page-run-a-node-further-reading-3-author")}
-
-
-
-
-
-
-
-
-
+
+
+ {t("page-run-a-node-rasp-pi-title")}
+
+ {t("page-run-a-node-rasp-pi-description")}
+
+ -
+
+ {t("page-run-a-node-rasp-pi-note-2-link")}
+ {" "}
+ - {t("page-run-a-node-rasp-pi-note-2-description")}
+
+ -
+
+ {t("page-run-a-node-rasp-pi-note-3-link")}
+ {" "}
+ - {t("page-run-a-node-rasp-pi-note-3-description")}
+
+
+
+
+
+
-
-
- {t("page-run-a-node-staking-title")}
- {t("page-run-a-node-staking-description")}
-
-
- {t("page-run-a-node-staking-link")}
-
-
-
-
-
-
-
- {t("page-run-a-node-staking-plans-title")}
-
-
-
-
-
- {t("page-run-a-node-staking-plans-ethstaker-link-description")} -{" "}
-
- {t("page-run-a-node-staking-plans-ethstaker-link-label")}
-
-
-
-
- {t("page-run-a-node-rasp-pi-title")}
-
- {t("page-run-a-node-rasp-pi-description")}
-
- -
-
- {t("page-run-a-node-rasp-pi-note-2-link")}
- {" "}
- - {t("page-run-a-node-rasp-pi-note-2-description")}
-
- -
-
- {t("page-run-a-node-rasp-pi-note-3-link")}
- {" "}
- - {t("page-run-a-node-rasp-pi-note-3-description")}
-
-
-
-
-
-
-
-
-
+
+
+
+ >
)
}
diff --git a/app/[locale]/run-a-node/page-jsonld.tsx b/app/[locale]/run-a-node/page-jsonld.tsx
new file mode 100644
index 00000000000..2385e13360c
--- /dev/null
+++ b/app/[locale]/run-a-node/page-jsonld.tsx
@@ -0,0 +1,119 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function RunANodePageJsonLD({
+ locale,
+ lastEditLocaleTimestamp,
+ contributors,
+}: {
+ locale: Lang | undefined
+ lastEditLocaleTimestamp: string
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-run-a-node",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/run-a-node/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Run a Node page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-run-a-node-title"),
+ description: t("page-run-a-node-hero-subtitle"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-run-a-node-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the run a node article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-run-a-node-title"),
+ description: t("page-run-a-node-hero-subtitle"),
+ image: "https://ethereum.org/images/run-a-node/ethereum-inside.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ contributor: contributorList,
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Running an Ethereum Node",
+ description:
+ "Guide to running your own Ethereum node, benefits, and requirements",
+ },
+ dateModified: lastEditLocaleTimestamp,
+ }
+
+ return
+}
diff --git a/app/[locale]/run-a-node/page.tsx b/app/[locale]/run-a-node/page.tsx
index 178fd003ff8..a94b497e2a8 100644
--- a/app/[locale]/run-a-node/page.tsx
+++ b/app/[locale]/run-a-node/page.tsx
@@ -14,6 +14,7 @@ import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import RunANodePage from "./_components/run-a-node"
+import RunANodePageJsonLD from "./page-jsonld"
const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const { locale } = await params
@@ -35,9 +36,15 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
return (
+
)
diff --git a/app/[locale]/stablecoins/page-jsonld.tsx b/app/[locale]/stablecoins/page-jsonld.tsx
new file mode 100644
index 00000000000..0fd62fe08f6
--- /dev/null
+++ b/app/[locale]/stablecoins/page-jsonld.tsx
@@ -0,0 +1,140 @@
+import { getTranslations } from "next-intl/server"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function StablecoinsPageJsonLD({
+ locale,
+ features,
+ contributors,
+}) {
+ const t = await getTranslations({
+ namespace: "page-stablecoins",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/stablecoins/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Stablecoins page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-stablecoins-meta-title"),
+ description: t("page-stablecoins-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-stablecoins-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the stablecoins article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-stablecoins-title"),
+ description: t("page-stablecoins-meta-description"),
+ image: "https://ethereum.org/images/stablecoins/hero.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ contributor: contributorList,
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Stablecoins",
+ description:
+ "Digital currencies pegged to stable assets like the US dollar",
+ },
+ }
+
+ // JSON-LD for stablecoin types as ItemList
+ const stablecoinTypesJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "ItemList",
+ name: "Types of Stablecoins",
+ description:
+ "Different categories of stablecoins based on their backing mechanisms",
+ numberOfItems: features.length,
+ itemListElement: features.map((feature, index) => ({
+ "@type": "ListItem",
+ position: index + 1,
+ item: {
+ "@type": "Product",
+ name: feature.title,
+ description:
+ typeof feature.description === "string"
+ ? feature.description
+ : feature.title,
+ category: "Digital Currency",
+ additionalType: "https://schema.org/FinancialProduct",
+ },
+ })),
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/stablecoins/page.tsx b/app/[locale]/stablecoins/page.tsx
index d4c3ce455f9..c847d878461 100644
--- a/app/[locale]/stablecoins/page.tsx
+++ b/app/[locale]/stablecoins/page.tsx
@@ -6,7 +6,7 @@ import {
setRequestLocale,
} from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import CalloutBannerSSR from "@/components/CalloutBannerSSR"
import DataProductCard from "@/components/DataProductCard"
@@ -31,6 +31,7 @@ import InlineLink from "@/components/ui/Link"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { cn } from "@/lib/utils/cn"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { dataLoader } from "@/lib/utils/data/dataLoader"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
@@ -38,6 +39,7 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import { BASE_TIME_UNIT } from "@/lib/constants"
import { stablecoins } from "./data"
+import StablecoinsPageJsonLD from "./page-jsonld"
import { fetchEthereumStablecoinsData } from "@/lib/api/stablecoinsData"
import sparkfiImg from "@/public/images/dapps/sparkfi.png"
@@ -420,326 +422,353 @@ async function Page({ params }: { params: Promise<{ locale: Lang }> }) {
},
]
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "stablecoins",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
-
-
-
-
-
-
-
-
{t("page-stablecoins-why-stablecoins")}
-
- {t("page-stablecoins-prices-definition")}{" "}
-
- {t("page-stablecoins-prices-definition-how")}
-
-
-
-
-
-
- {tokens.map((token, index) => (
-
-
-
- ))}
-
-
-
-
- {t("page-stablecoins-bitcoin-pizza")}
-
-
- {t("page-stablecoins-bitcoin-pizza-body")}{" "}
-
-
-
-
-
-
-
-
{t("page-stablecoins-find-stablecoin")}
-
-
- {t("page-stablecoins-find-stablecoin-intro")}
-
-
- -
+ <>
+
+
+
+
+
+
+
+
+
+ {t("page-stablecoins-why-stablecoins")}
+
+
+ {t("page-stablecoins-prices-definition")}{" "}
- {t("page-stablecoins-find-stablecoin-types-link")}
-
-
-
-
-
- {t("page-stablecoins-find-stablecoin-how-to-get-them")}
+ {t("page-stablecoins-prices-definition-how")}
-
-
+
+
+
+
+ {tokens.map((token, index) => (
+
+
+
+ ))}
+
+
+
+
+ {t("page-stablecoins-bitcoin-pizza")}
+
+
+ {t("page-stablecoins-bitcoin-pizza-body")}{" "}
+
+
+
+
-
- {t("page-stablecoins-editors-choice")}
-
- {t("page-stablecoins-editors-choice-intro")}
+
+
+
{t("page-stablecoins-find-stablecoin")}
+
+
+ {t("page-stablecoins-find-stablecoin-intro")}
+
+
+ -
+
+ {t("page-stablecoins-find-stablecoin-types-link")}
+
+
+ -
+
+ {t("page-stablecoins-find-stablecoin-how-to-get-them")}
+
+
+
+
+
+
+ {t("page-stablecoins-editors-choice")}
+
+
+ {t("page-stablecoins-editors-choice-intro")}
+
-
- {editorsChoices.map((choice, idx) => (
-
-
-
-
{choice.title}
-
{choice.body}
-
-
-
-
-
- {choice.swapButtonText}
-
+
+ {editorsChoices.map((choice, idx) => (
+
+
+
+
{choice.title}
+
{choice.body}
+
+
+
+
+
+ {choice.swapButtonText}
+
+
+
+
+ {choice.learnButtonText}
+
+
+
+
+
+
+
+
+
+
+
+
+ {choice.marketCap ? (
+
+ {choice.marketCap}
+
+ ) : (
+ -
+ )}
-
-
- {choice.learnButtonText}
-
+
+ {t(
+ "page-stablecoins-stablecoins-table-header-column-2"
+ )}
-
-
-
-
-
-
-
-
-
-
- {choice.marketCap ? (
-
- {choice.marketCap}
-
- ) : (
- -
- )}
-
-
- {t(
- "page-stablecoins-stablecoins-table-header-column-2"
- )}
-
+
-
- ))}
-
-
-
- {t("page-stablecoins-top-coins")}
-
-
-
-
-
-
- {t("page-stablecoins-top-coins-intro")}{" "}
- {t("page-stablecoins-top-coins-intro-code")}
-
-
-
- {/* CLIENT SIDE */}
-
-
+ ))}
+
+
+
+ {t("page-stablecoins-top-coins")}
+
+
+
+
-
- {t("page-stablecoins-get-stablecoins")}
-
- {/* CLIENT SIDE */}
-
-
-
-
-
-
-
-
- {t("page-stablecoins-explore-dapps")}
-
-
- {t("page-stablecoins-more-defi-button")}
-
-
-
- {t("page-stablecoins-save-stablecoins")}
-
-
- {t("page-stablecoins-save-stablecoins-body")}
+ {t("page-stablecoins-top-coins-intro")}{" "}
+ {t("page-stablecoins-top-coins-intro-code")}
-
- {t("page-stablecoins-interest-earning-dapps")}
-
-
{t("page-stablecoins-saving")}
-
-
- {dapps.map((dapp, idx) => (
-
- ))}
+
+ {/* CLIENT SIDE */}
+
-
-
-
- {t("page-stablecoins-types-of-stablecoin")}
-
-
- {features.map((feature) => (
-
+ {t("page-stablecoins-get-stablecoins")}
+
+ {/* CLIENT SIDE */}
+
+
+
+
+
+
+
+
+ {t("page-stablecoins-explore-dapps")}
+
+
-
- {feature.title}
-
+ {t("page-stablecoins-more-defi-button")}
+
+
+
+ {t("page-stablecoins-save-stablecoins")}
+
+
+
+ {t("page-stablecoins-save-stablecoins-body")}
+
+
+ {t("page-stablecoins-interest-earning-dapps")}
+
+
{t("page-stablecoins-saving")}
+
+
+
+ {dapps.map((dapp, idx) => (
+
))}
-
- {features.map((feature) => (
-
-
-
-
-
-
-
{feature.title}
-
{feature.description}
-
- {feature.pros && (
-
-
- {t("pros")}
-
-
- {feature.pros.map((pro, idx) => (
- - {pro}
- ))}
-
-
- )}
- {feature.cons && (
+
+
+
+
+
+ {t("page-stablecoins-types-of-stablecoin")}
+
+
+
+ {features.map((feature) => (
+
+
+ {feature.title}
+
+ ))}
+
+ {features.map((feature) => (
+
+
+
+
+
+
+
+ {feature.title}
+
+
{feature.description}
+
+ {feature.pros && (
+
+
+ {t("pros")}
+
+
+ {feature.pros.map((pro, idx) => (
+ - {pro}
+ ))}
+
+
+ )}
+ {feature.cons && (
+
+
+ {t("cons")}
+
+
+ {feature.cons.map((con, idx) => (
+ - {con}
+ ))}
+
+
+ )}
+
+ {feature.links && feature.links.length > 0 && (
-
- {t("cons")}
+
+ {t("example-projects")}
- {feature.cons.map((con, idx) => (
- - {con}
+ {feature.links.map((link, idx) => (
+ -
+
+ {link.text}
+
+
))}
)}
- {feature.links && feature.links.length > 0 && (
-
-
- {t("example-projects")}
-
-
- {feature.links.map((link, idx) => (
- -
-
- {link.text}
-
-
- ))}
-
-
- )}
-
-
- ))}
-
-
-
-
{t("page-stablecoins-tools-title")}
-
-
:not(:nth-last-child(-n+2))]:border-b md:[&_[aria-labelledby='category-name']>:nth-last-child(-n+2)]:border-b-0",
- "[&_img]:shadow-none"
- )}
- >
-
+
+ ))}
+
+
+
-
-
-
-
+
+
+
+ >
)
}
diff --git a/app/[locale]/staking/deposit-contract/_components/deposit-contract.tsx b/app/[locale]/staking/deposit-contract/_components/deposit-contract.tsx
index 46144e8bf84..b3ee417fd78 100644
--- a/app/[locale]/staking/deposit-contract/_components/deposit-contract.tsx
+++ b/app/[locale]/staking/deposit-contract/_components/deposit-contract.tsx
@@ -3,7 +3,7 @@ import { useEffect, useState } from "react"
import makeBlockie from "ethereum-blockies-base64"
import { Clipboard, ClipboardCheck } from "lucide-react"
-import type { ChildOnlyProp, TranslationKey } from "@/lib/types"
+import type { ChildOnlyProp, Lang, TranslationKey } from "@/lib/types"
import Breadcrumbs from "@/components/Breadcrumbs"
import CardList from "@/components/CardList"
@@ -145,7 +145,7 @@ const CHUNKED_ADDRESS =
const blockieSrc = makeBlockie(DEPOSIT_CONTRACT_ADDRESS)
-const DepositContractPage = () => {
+const DepositContractPage = ({ locale }: { locale: Lang }) => {
const pathname = usePathname()
const { t } = useTranslation("page-staking-deposit-contract")
@@ -255,163 +255,249 @@ const DepositContractPage = () => {
const textToSpeechEmoji = state.isSpeechActive
? ":speaker_high_volume:"
: ":speaker:"
+
+ // JSON-LD structured data for the Deposit Contract page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": `https://ethereum.org/${locale}/staking/deposit-contract/`,
+ name: t("page-staking-deposit-contract-title"),
+ description: t("page-staking-deposit-contract-subtitle"),
+ url: `https://ethereum.org/${locale}/staking/deposit-contract/`,
+ inLanguage: locale,
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: `https://ethereum.org/${locale}/`,
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: "Staking",
+ item: `https://ethereum.org/${locale}/staking/`,
+ },
+ {
+ "@type": "ListItem",
+ position: 3,
+ name: t("page-staking-deposit-contract-title"),
+ item: `https://ethereum.org/${locale}/staking/deposit-contract/`,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ }
+
+ // JSON-LD for the deposit contract article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-staking-deposit-contract-title"),
+ description: t("page-staking-deposit-contract-subtitle"),
+ author: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Deposit Contract",
+ description:
+ "Official Ethereum 2.0 deposit contract address for staking validators",
+ },
+ }
+
return (
-
-
-
-
- {t("page-staking-deposit-contract-title")}
- {t("page-staking-deposit-contract-subtitle")}
- {t("page-staking-deposit-contract-h2")}
-
- {t("page-staking-deposit-contract-staking")}{" "}
-
- {t("page-staking-deposit-contract-staking-more-link")}
-
-
-
- {t("page-staking-deposit-contract-launchpad")}
-
- {t("page-staking-deposit-contract-staking-check")}
-
- {t("page-staking-deposit-contract-staking-check-desc")}
-
-
-
-
-
-
- {t("page-staking-deposit-contract-address-check-btn")}
-
-
- {!state.showAddress && (
- <>
-
-
- {t("page-staking-deposit-contract-confirm-address")}
-
-
-
-
-
-
-
-
- setState({ ...state, showAddress: !state.showAddress })
- }
- >
-
- {t("page-staking-deposit-contract-reveal-address-btn")}
-
- >
- )}
- {state.showAddress && (
- <>
-
-
+ <>
+
+
+
+
+
+
+
+
+ {t("page-staking-deposit-contract-title")}
+ {t("page-staking-deposit-contract-subtitle")}
+ {t("page-staking-deposit-contract-h2")}
+
+ {t("page-staking-deposit-contract-staking")}{" "}
+
+ {t("page-staking-deposit-contract-staking-more-link")}
+
+
+
+ {t("page-staking-deposit-contract-launchpad")}
+
+ {t("page-staking-deposit-contract-staking-check")}
+
+ {t("page-staking-deposit-contract-staking-check-desc")}
+
+
+
+
+
+
+ {t("page-staking-deposit-contract-address-check-btn")}
+
+
+ {!state.showAddress && (
+ <>
+
- {t("page-staking-deposit-contract-address")}
+ {t("page-staking-deposit-contract-confirm-address")}
-
- {t("page-staking-deposit-contract-address-caption")}
-
-
-
-
- {state.browserHasTextToSpeechSupport && (
-
-
-
- {" "}
-
+
+
+
+
+
- )}
-
- {CHUNKED_ADDRESS}
-
-
-
- {(isCopied) => (
-
- {!isCopied ? (
- <>
- {t("page-staking-deposit-contract-copy")}
-
- >
- ) : (
- <>
- {t("page-staking-deposit-contract-copied")}
-
- >
- )}
-
- )}
-
+
+ setState({ ...state, showAddress: !state.showAddress })
+ }
+ >
+
+ {t("page-staking-deposit-contract-reveal-address-btn")}
+
+ >
+ )}
+ {state.showAddress && (
+ <>
+
+
+
+ {t("page-staking-deposit-contract-address")}
+
+
+ {t("page-staking-deposit-contract-address-caption")}
+
+
+
+
+ {state.browserHasTextToSpeechSupport && (
+
+
+
+ {" "}
+
+
+ )}
+
+ {CHUNKED_ADDRESS}
+
+
+
+ {(isCopied) => (
+
+ {!isCopied ? (
+ <>
+ {t("page-staking-deposit-contract-copy")}
+
+ >
+ ) : (
+ <>
+ {t("page-staking-deposit-contract-copied")}
+
+ >
+ )}
+
+ )}
+
+
+ {t("page-staking-deposit-contract-blockexplorer")}
+
+
+ >
+ )}
+
+
+ {t("page-staking-deposit-contract-warning-2")}{" "}
- {t("page-staking-deposit-contract-blockexplorer")}
+ {t("page-staking-deposit-contract-launchpad-2")}
-
- >
- )}
-
-
- {t("page-staking-deposit-contract-warning-2")}{" "}
-
- {t("page-staking-deposit-contract-launchpad-2")}
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/staking/deposit-contract/page.tsx b/app/[locale]/staking/deposit-contract/page.tsx
index e6a4d3f3da3..7d48a4af20f 100644
--- a/app/[locale]/staking/deposit-contract/page.tsx
+++ b/app/[locale]/staking/deposit-contract/page.tsx
@@ -28,7 +28,7 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
return (
-
+
)
}
diff --git a/app/[locale]/staking/page-jsonld.tsx b/app/[locale]/staking/page-jsonld.tsx
new file mode 100644
index 00000000000..37bb723e903
--- /dev/null
+++ b/app/[locale]/staking/page-jsonld.tsx
@@ -0,0 +1,178 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function StakingPageJsonLD({
+ locale,
+ lastEditLocaleTimestamp,
+ contributors,
+}: {
+ locale: Lang | undefined
+ lastEditLocaleTimestamp: string
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-staking",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/staking/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Staking page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-staking-meta-title"),
+ description: t("page-staking-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-staking-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the staking article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-staking-hero-title"),
+ description: t("page-staking-meta-description"),
+ image: "https://ethereum.org/images/upgrades/upgrade_rhino.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ contributor: contributorList,
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Staking",
+ description:
+ "Guide to staking ETH, earning rewards, and securing the Ethereum network",
+ },
+ dateModified: lastEditLocaleTimestamp,
+ }
+
+ // JSON-LD for the FAQ section
+ const faqJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "FAQPage",
+ mainEntity: [
+ {
+ "@type": "Question",
+ name: t("page-staking-faq-4-question"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-staking-faq-4-answer-p1")} ${t("page-staking-faq-4-answer-p2")} ${t("page-staking-faq-4-answer-p3")}`.replace(
+ /<[^>]*>/g,
+ ""
+ ),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-staking-faq-5-question"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-staking-faq-5-answer-p1")} ${t("page-staking-faq-5-answer-p2")}`.replace(
+ /<[^>]*>/g,
+ ""
+ ),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-staking-faq-1-question"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-staking-faq-1-answer").replace(/<[^>]*>/g, ""),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-staking-faq-2-question"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-staking-faq-2-answer").replace(/<[^>]*>/g, ""),
+ },
+ },
+ {
+ "@type": "Question",
+ name: t("page-staking-faq-3-question"),
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: `${t("page-staking-faq-3-answer-p1")} ${t("page-staking-faq-3-answer-p2")}`.replace(
+ /<[^>]*>/g,
+ ""
+ ),
+ },
+ },
+ ],
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/staking/page.tsx b/app/[locale]/staking/page.tsx
index 78c0241a562..602411ae4c2 100644
--- a/app/[locale]/staking/page.tsx
+++ b/app/[locale]/staking/page.tsx
@@ -23,6 +23,7 @@ import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import { BASE_TIME_UNIT } from "@/lib/constants"
import StakingPage from "./_components/staking"
+import StakingPageJsonLD from "./page-jsonld"
const fetchBeaconchainData = async (): Promise
=> {
// Fetch Beaconcha.in data
@@ -83,10 +84,16 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
return (
+
)
diff --git a/app/[locale]/start/page-jsonld.tsx b/app/[locale]/start/page-jsonld.tsx
new file mode 100644
index 00000000000..5a86a796cc6
--- /dev/null
+++ b/app/[locale]/start/page-jsonld.tsx
@@ -0,0 +1,116 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function StartPageJsonLD({
+ locale,
+ contributors,
+}: {
+ locale: Lang | undefined
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-start",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/start/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Start page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-start-meta-title"),
+ description: t("page-start-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-start-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the start guide article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-start-title"),
+ description: t("page-start-meta-description"),
+ image: "https://ethereum.org/images/heroes/developers-hub-hero.jpg",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ contributor: contributorList,
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Getting Started with Ethereum",
+ description:
+ "Beginner's guide to getting started with Ethereum, crypto wallets, and web3",
+ },
+ }
+
+ return
+}
diff --git a/app/[locale]/start/page.tsx b/app/[locale]/start/page.tsx
index 33ec5cf8cc4..70d9da71b1b 100644
--- a/app/[locale]/start/page.tsx
+++ b/app/[locale]/start/page.tsx
@@ -5,7 +5,7 @@ import {
setRequestLocale,
} from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import I18nProvider from "@/components/I18nProvider"
import { Image } from "@/components/Image"
@@ -13,10 +13,13 @@ import MainArticle from "@/components/MainArticle"
import StartWithEthereumFlow from "@/components/StartWithEthereumFlow"
import ShareModal from "@/components/StartWithEthereumFlow/ShareModal"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import { getNewToCryptoWallets } from "@/lib/utils/wallets"
+import StartPageJsonLD from "./page-jsonld"
+
import HeroImage from "@/public/images/heroes/developers-hub-hero.png"
import ManDogeImage from "@/public/images/start-with-ethereum/man-doge-playing.png"
@@ -37,44 +40,54 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
supportedLanguages: [],
}))
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "start",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
-
-
-
-
-
-
-
-
{t("page-start-title")}
-
{t("page-start-subtitle")}
+ <>
+
+
+
+
-
-
-
+
+
+
{t("page-start-title")}
+
{t("page-start-subtitle")}
-
-
-
{t("page-start-share-section-title")}
-
{t("page-start-share-section-description")}
-
-
-
+
+
+
-
-
+
+
+
+
{t("page-start-share-section-title")}
+
{t("page-start-share-section-description")}
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+ >
)
}
diff --git a/app/[locale]/trillion-dollar-security/page-jsonld.tsx b/app/[locale]/trillion-dollar-security/page-jsonld.tsx
new file mode 100644
index 00000000000..2dafb0560ed
--- /dev/null
+++ b/app/[locale]/trillion-dollar-security/page-jsonld.tsx
@@ -0,0 +1,116 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function TrillionDollarSecurityPageJsonLD({
+ locale,
+ contributors,
+}: {
+ locale: Lang | undefined
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-trillion-dollar-security",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/trillion-dollar-security/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Trillion-Dollar Security page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-trillion-dollar-security-meta-title"),
+ description: t("page-trillion-dollar-security-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-trillion-dollar-security-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the security report article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-trillion-dollar-security-title"),
+ description: t("page-trillion-dollar-security-meta-description"),
+ image: "https://ethereum.org/images/trillion-dollar-security/hero.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ contributor: contributorList,
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Security",
+ description:
+ "Comprehensive security analysis of Ethereum's trillion-dollar ecosystem",
+ },
+ }
+
+ return
+}
diff --git a/app/[locale]/trillion-dollar-security/page.tsx b/app/[locale]/trillion-dollar-security/page.tsx
index 7e0416be883..8cf7a977156 100644
--- a/app/[locale]/trillion-dollar-security/page.tsx
+++ b/app/[locale]/trillion-dollar-security/page.tsx
@@ -2,7 +2,7 @@ import React from "react"
import Image from "next/image"
import { getTranslations, setRequestLocale } from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import MainArticle from "@/components/MainArticle"
import { ButtonLink } from "@/components/ui/buttons/Button"
@@ -14,8 +14,11 @@ import {
} from "@/components/ui/card"
import InlineLink, { BaseLink as Link } from "@/components/ui/Link"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
+import TrillionDollarSecurityPageJsonLD from "./page-jsonld"
+
import TdsHero from "@/public/images/trillion-dollar-security/hero.png"
import TdsReport from "@/public/images/trillion-dollar-security/report.png"
@@ -50,958 +53,1041 @@ const TdsPage = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
namespace: "page-trillion-dollar-security",
})
- return (
-
- {/* Hero Section */}
-
-
-
-
- {t("page-trillion-dollar-security-subtitle")}
-
-
- {t("page-trillion-dollar-security-title")}
-
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "trillion-dollar-security",
+ locale as Lang,
+ commitHistoryCache
+ )
-
- {/* Right: Download Card */}
-
-
-
-
-
{t("page-trillion-dollar-security-hero-paragraph-1")}
-
{t("page-trillion-dollar-security-hero-paragraph-2")}
-
- -
- {t.rich("page-trillion-dollar-security-hero-paragraph-3", {
- b: (chunks) => {chunks},
- })}
-
- -
- {t.rich("page-trillion-dollar-security-hero-paragraph-4", {
- b: (chunks) => {chunks},
- })}
-
-
+ return (
+ <>
+
+
+ {/* Hero Section */}
+
+
+
+
+ {t("page-trillion-dollar-security-subtitle")}
+
+
+ {t("page-trillion-dollar-security-title")}
+
-
+
+ {/* Right: Download Card */}
+
+
+
{t("page-trillion-dollar-security-hero-paragraph-1")}
+
{t("page-trillion-dollar-security-hero-paragraph-2")}
+
+ -
+ {t.rich("page-trillion-dollar-security-hero-paragraph-3", {
+ b: (chunks) => {chunks},
+ })}
+
+ -
+ {t.rich("page-trillion-dollar-security-hero-paragraph-4", {
+ b: (chunks) => {chunks},
+ })}
+
+
-
- {t.rich("page-trillion-dollar-security-hero-paragraph-5", {
- a: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
-
{t("page-trillion-dollar-security-hero-paragraph-6")}
-
-
- -
-
- {t("page-trillion-dollar-security-user-experience-title")}
-
-
- {t(
- "page-trillion-dollar-security-user-experience-description"
+
+
-
- -
-
- {t("page-trillion-dollar-security-smart-contract-title")}
-
-
- {t(
- "page-trillion-dollar-security-smart-contract-description"
- )}
-
-
- -
-
- {t("page-trillion-dollar-security-infrastructure-title")}
-
-
- {t(
- "page-trillion-dollar-security-infrastructure-description"
- )}
-
-
- -
-
- {t("page-trillion-dollar-security-consensus-title")}
-
-
- {t("page-trillion-dollar-security-consensus-description")}
-
-
- -
-
- {t("page-trillion-dollar-security-incident-title")}
-
-
- {t("page-trillion-dollar-security-incident-description")}
-
-
- -
-
- {t("page-trillion-dollar-security-social-title")}
-
-
- {t("page-trillion-dollar-security-social-description")}
-
-
-
+ />
+
-
- {t("page-trillion-dollar-security-hero-closing-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-hero-closing-paragraph-2")}
-
-
- {t("page-trillion-dollar-security-hero-closing-paragraph-3")}
-
+
+ {t.rich("page-trillion-dollar-security-hero-paragraph-5", {
+ a: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
+ {t("page-trillion-dollar-security-hero-paragraph-6")}
-
- -
- {t("page-trillion-dollar-security-feedback-question-1")}
-
- -
- {t("page-trillion-dollar-security-feedback-question-2")}
-
- -
- {t("page-trillion-dollar-security-feedback-question-3")}
-
-
+
+ -
+
+ {t("page-trillion-dollar-security-user-experience-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-user-experience-description"
+ )}
+
+
+ -
+
+ {t("page-trillion-dollar-security-smart-contract-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-smart-contract-description"
+ )}
+
+
+ -
+
+ {t("page-trillion-dollar-security-infrastructure-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-infrastructure-description"
+ )}
+
+
+ -
+
+ {t("page-trillion-dollar-security-consensus-title")}
+
+
+ {t("page-trillion-dollar-security-consensus-description")}
+
+
+ -
+
+ {t("page-trillion-dollar-security-incident-title")}
+
+
+ {t("page-trillion-dollar-security-incident-description")}
+
+
+ -
+
+ {t("page-trillion-dollar-security-social-title")}
+
+
+ {t("page-trillion-dollar-security-social-description")}
+
+
+
-
- {t.rich("page-trillion-dollar-security-contact-paragraph", {
- a: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
-
-
-
-
+
+ {t("page-trillion-dollar-security-hero-closing-paragraph-1")}
+
+
+ {t("page-trillion-dollar-security-hero-closing-paragraph-2")}
+
+
+ {t("page-trillion-dollar-security-hero-closing-paragraph-3")}
+
-
- {/* Main Content Sections - Each with its own sticky heading */}
-
- {/* User Experience section */}
-
-
-
- 1. {t("page-trillion-dollar-security-user-experience-title")}
-
-
{t("page-trillion-dollar-security-section-1-intro")}
-
-
-
-
-
- {t("page-trillion-dollar-security-section-1-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-1-paragraph-2")}
-
-
- {t("page-trillion-dollar-security-section-1-paragraph-3")}
-
-
+
+ -
+ {t("page-trillion-dollar-security-feedback-question-1")}
+
+ -
+ {t("page-trillion-dollar-security-feedback-question-2")}
+
+ -
+ {t("page-trillion-dollar-security-feedback-question-3")}
+
+
-
-
- {t("page-trillion-dollar-security-section-1-1-title")}
-
-
- {t("page-trillion-dollar-security-section-1-1-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-1-1-paragraph-2")}
-
-
- {t("page-trillion-dollar-security-section-1-1-paragraph-3")}
-
-
- {t("page-trillion-dollar-security-section-1-1-paragraph-4")}
-
-
- {t("page-trillion-dollar-security-section-1-1-paragraph-5")}
-
-
-
-
- {t("page-trillion-dollar-security-section-1-2-title")}
-
-
- {t("page-trillion-dollar-security-section-1-2-paragraph")}
-
-
-
-
- {t("page-trillion-dollar-security-section-1-3-title")}
-
-
- {t("page-trillion-dollar-security-section-1-3-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-1-3-paragraph-2")}
-
-
- {t("page-trillion-dollar-security-section-1-3-paragraph-3")}
-
-
- {t("page-trillion-dollar-security-section-1-3-paragraph-4")}
-
-
-
-
- {t("page-trillion-dollar-security-section-1-4-title")}
-
-
- {t("page-trillion-dollar-security-section-1-4-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-1-4-paragraph-2")}
-
-
-
-
- {t("page-trillion-dollar-security-section-1-5-title")}
-
-
- {t("page-trillion-dollar-security-section-1-5-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-1-5-paragraph-2")}
-
-
- {t("page-trillion-dollar-security-section-1-5-paragraph-3")}
-
-
-
-
- {t("page-trillion-dollar-security-section-1-6-title")}
-
-
- {t("page-trillion-dollar-security-section-1-6-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-1-6-paragraph-2")}
-
-
+
+ {t.rich("page-trillion-dollar-security-contact-paragraph", {
+ a: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
-
+
+
- {/* Smart Contract Security section */}
-
-
-
- 2. {t("page-trillion-dollar-security-smart-contract-title")}
-
-
{t("page-trillion-dollar-security-section-2-intro")}
-
-
-
-
-
- {t("page-trillion-dollar-security-section-2-paragraph-1")}
-
-
- -
- {t("page-trillion-dollar-security-section-2-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-2-list-2")}
-
- -
- {t("page-trillion-dollar-security-section-2-list-3")}
-
- -
- {t("page-trillion-dollar-security-section-2-list-4")}
-
- -
- {t("page-trillion-dollar-security-section-2-list-5")}
-
- -
- {t("page-trillion-dollar-security-section-2-list-6")}
-
-
-
- {t("page-trillion-dollar-security-section-2-paragraph-2")}
-
-
+
+ {/* Main Content Sections - Each with its own sticky heading */}
+
+ {/* User Experience section */}
+
+
+
+ 1. {t("page-trillion-dollar-security-user-experience-title")}
+
+
{t("page-trillion-dollar-security-section-1-intro")}
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-1-paragraph-1")}
+
+
+ {t("page-trillion-dollar-security-section-1-paragraph-2")}
+
+
+ {t("page-trillion-dollar-security-section-1-paragraph-3")}
+
+
-
-
- {t("page-trillion-dollar-security-section-2-1-title")}
-
-
- {t("page-trillion-dollar-security-section-2-1-paragraph")}
-
-
- -
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-1"
- )}
- .
- {" "}
+
+
+ {t("page-trillion-dollar-security-section-1-1-title")}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-1"
+ "page-trillion-dollar-security-section-1-1-paragraph-1"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-2"
- )}
-
- ,{" "}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-2"
+ "page-trillion-dollar-security-section-1-1-paragraph-2"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-3"
- )}
-
- ,{" "}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-3"
+ "page-trillion-dollar-security-section-1-1-paragraph-3"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-4"
- )}
- .
- {" "}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-4"
+ "page-trillion-dollar-security-section-1-1-paragraph-4"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-5"
- )}
-
- ,{" "}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-5"
+ "page-trillion-dollar-security-section-1-1-paragraph-5"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-6"
- )}
-
- ,{" "}
+
+
+
+
+ {t("page-trillion-dollar-security-section-1-2-title")}
+
+
+ {t("page-trillion-dollar-security-section-1-2-paragraph")}
+
+
+
+
+ {t("page-trillion-dollar-security-section-1-3-title")}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-6"
+ "page-trillion-dollar-security-section-1-3-paragraph-1"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-7"
- )}
- .
- {" "}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-7"
+ "page-trillion-dollar-security-section-1-3-paragraph-2"
)}
-
-
-
-
- {t(
- "page-trillion-dollar-security-section-2-1-list-title-8"
- )}
- .
- {" "}
+
+
{t(
- "page-trillion-dollar-security-section-2-1-list-desc-8"
+ "page-trillion-dollar-security-section-1-3-paragraph-3"
)}
-
-
-
-
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-3-paragraph-4"
+ )}
+
+
+
+
+ {t("page-trillion-dollar-security-section-1-4-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-4-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-4-paragraph-2"
+ )}
+
+
+
+
+ {t("page-trillion-dollar-security-section-1-5-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-5-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-5-paragraph-2"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-5-paragraph-3"
+ )}
+
+
+
+
+ {t("page-trillion-dollar-security-section-1-6-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-6-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-1-6-paragraph-2"
+ )}
+
+
+
+
+
+
+ {/* Smart Contract Security section */}
+
+
+
+ 2. {t("page-trillion-dollar-security-smart-contract-title")}
+
+
{t("page-trillion-dollar-security-section-2-intro")}
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-2-paragraph-1")}
+
+
+ -
+ {t("page-trillion-dollar-security-section-2-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-2-list-2")}
+
+ -
+ {t("page-trillion-dollar-security-section-2-list-3")}
+
+ -
+ {t("page-trillion-dollar-security-section-2-list-4")}
+
+ -
+ {t("page-trillion-dollar-security-section-2-list-5")}
+
+ -
+ {t("page-trillion-dollar-security-section-2-list-6")}
+
+
+
+ {t("page-trillion-dollar-security-section-2-paragraph-2")}
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-2-1-title")}
+
+
+ {t("page-trillion-dollar-security-section-2-1-paragraph")}
+
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-1"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-1-list-title-9"
+ "page-trillion-dollar-security-section-2-1-list-desc-1"
)}
- .
-
-
-
-
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-2"
+ )}
+
+ ,{" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-2"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-3"
+ )}
+
+ ,{" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-3"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-4"
+ )}
+ .
+ {" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-4"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-5"
+ )}
+
+ ,{" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-5"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-6"
+ )}
+
+ ,{" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-6"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-7"
+ )}
+ .
+ {" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-7"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-8"
+ )}
+ .
+ {" "}
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-desc-8"
+ )}
+
+
-
+
+ {t(
+ "page-trillion-dollar-security-section-2-1-list-title-9"
+ )}
+ .
+
+
+
+
-
-
- {t("page-trillion-dollar-security-section-2-2-title")}
-
-
- {t("page-trillion-dollar-security-section-2-2-paragraph")}
-
-
- -
-
+
+
+ {t("page-trillion-dollar-security-section-2-2-title")}
+
+
+ {t("page-trillion-dollar-security-section-2-2-paragraph")}
+
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-1"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-1"
+ "page-trillion-dollar-security-section-2-2-list-desc-1"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-1"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-2"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-2"
+ "page-trillion-dollar-security-section-2-2-list-desc-2"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-2"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-3"
+ )}
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-3"
+ "page-trillion-dollar-security-section-2-2-list-desc-3"
)}
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-3"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-4"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-4"
+ "page-trillion-dollar-security-section-2-2-list-desc-4"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-4"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-5"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-5"
+ "page-trillion-dollar-security-section-2-2-list-desc-5"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-5"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-6"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-6"
+ "page-trillion-dollar-security-section-2-2-list-desc-6"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-6"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-2-2-list-title-7"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-2-2-list-title-7"
+ "page-trillion-dollar-security-section-2-2-list-desc-7"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-2-2-list-desc-7"
- )}
-
-
-
-
-
- {t("page-trillion-dollar-security-section-2-3-title")}
-
-
- {t("page-trillion-dollar-security-section-2-3-paragraph")}
-
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-2-3-title")}
+
+
+ {t("page-trillion-dollar-security-section-2-3-paragraph")}
+
+
-
-
+
- {/* Infrastructure & Cloud Security section */}
-
-
-
- 3. {t("page-trillion-dollar-security-infrastructure-title")}
-
-
{t("page-trillion-dollar-security-section-3-intro")}
-
-
-
-
-
- {t("page-trillion-dollar-security-section-3-paragraph-1")}
-
-
+ {/* Infrastructure & Cloud Security section */}
+
+
+
+ 3. {t("page-trillion-dollar-security-infrastructure-title")}
+
+
{t("page-trillion-dollar-security-section-3-intro")}
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-3-paragraph-1")}
+
+
-
-
- {t("page-trillion-dollar-security-section-3-1-title")}
-
-
- {t("page-trillion-dollar-security-section-3-1-paragraph")}
-
-
- -
-
+
+
+ {t("page-trillion-dollar-security-section-3-1-title")}
+
+
+ {t("page-trillion-dollar-security-section-3-1-paragraph")}
+
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-3-1-list-title-1"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-3-1-list-title-1"
+ "page-trillion-dollar-security-section-3-1-list-desc-1"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-3-1-list-desc-1"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-3-1-list-title-2"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-3-1-list-title-2"
+ "page-trillion-dollar-security-section-3-1-list-desc-2"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-3-1-list-desc-2"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-3-1-list-title-3"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-3-1-list-title-3"
+ "page-trillion-dollar-security-section-3-1-list-desc-3"
)}
- .
- {" "}
- {t(
- "page-trillion-dollar-security-section-3-1-list-desc-3"
+
+
+
+ {t.rich(
+ "page-trillion-dollar-security-section-3-1-paragraph-2",
+ {
+ a: (chunks) => (
+ {chunks}
+ ),
+ }
)}
-
-
-
- {t.rich(
- "page-trillion-dollar-security-section-3-1-paragraph-2",
- {
- a: (chunks) => (
- {chunks}
- ),
- }
- )}
-
-
+
+
-
-
- {t("page-trillion-dollar-security-section-3-2-title")}
-
-
- {t("page-trillion-dollar-security-section-3-2-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-3-2-paragraph-2")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-3-2-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-3-2-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-3-2-paragraph-2"
+ )}
+
+
-
-
- {t("page-trillion-dollar-security-section-3-3-title")}
-
-
- {t("page-trillion-dollar-security-section-3-3-paragraph")}
-
-
- -
- {t("page-trillion-dollar-security-section-3-3-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-3-3-list-2")}
-
- -
- {t("page-trillion-dollar-security-section-3-3-list-3")}
-
-
-
+
+
+ {t("page-trillion-dollar-security-section-3-3-title")}
+
+
+ {t("page-trillion-dollar-security-section-3-3-paragraph")}
+
+
+ -
+ {t("page-trillion-dollar-security-section-3-3-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-3-3-list-2")}
+
+ -
+ {t("page-trillion-dollar-security-section-3-3-list-3")}
+
+
+
-
-
- {t("page-trillion-dollar-security-section-3-4-title")}
-
-
- {t("page-trillion-dollar-security-section-3-4-paragraph")}
-
-
- -
-
+
+
+ {t("page-trillion-dollar-security-section-3-4-title")}
+
+
+ {t("page-trillion-dollar-security-section-3-4-paragraph")}
+
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-3-4-list-title-1"
+ )}
+
+ ,{" "}
{t(
- "page-trillion-dollar-security-section-3-4-list-title-1"
+ "page-trillion-dollar-security-section-3-4-list-desc-1"
)}
-
- ,{" "}
- {t(
- "page-trillion-dollar-security-section-3-4-list-desc-1"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-3-4-list-title-2"
+ )}
+
+ ,{" "}
{t(
- "page-trillion-dollar-security-section-3-4-list-title-2"
+ "page-trillion-dollar-security-section-3-4-list-desc-2"
)}
-
- ,{" "}
- {t(
- "page-trillion-dollar-security-section-3-4-list-desc-2"
- )}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-3-4-list-title-3"
+ )}
+
+ ,{" "}
{t(
- "page-trillion-dollar-security-section-3-4-list-title-3"
+ "page-trillion-dollar-security-section-3-4-list-desc-3"
)}
-
- ,{" "}
- {t(
- "page-trillion-dollar-security-section-3-4-list-desc-3"
- )}
-
-
-
+
+
+
-
-
- {t("page-trillion-dollar-security-section-3-5-title")}
-
-
- {t("page-trillion-dollar-security-section-3-5-paragraph")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-3-5-title")}
+
+
+ {t("page-trillion-dollar-security-section-3-5-paragraph")}
+
+
-
-
- {t("page-trillion-dollar-security-section-3-6-title")}
-
-
- {t("page-trillion-dollar-security-section-3-6-paragraph-1")}
-
-
- -
- {t("page-trillion-dollar-security-section-3-6-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-3-6-list-2")}
-
- -
- {t("page-trillion-dollar-security-section-3-6-list-3")}
-
- -
- {t("page-trillion-dollar-security-section-3-6-list-4")}
-
-
-
- {t("page-trillion-dollar-security-section-3-6-paragraph-2")}
-
+
+
+ {t("page-trillion-dollar-security-section-3-6-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-3-6-paragraph-1"
+ )}
+
+
+ -
+ {t("page-trillion-dollar-security-section-3-6-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-3-6-list-2")}
+
+ -
+ {t("page-trillion-dollar-security-section-3-6-list-3")}
+
+ -
+ {t("page-trillion-dollar-security-section-3-6-list-4")}
+
+
+
+ {t(
+ "page-trillion-dollar-security-section-3-6-paragraph-2"
+ )}
+
+
-
-
+
- {/* Consensus Protocol section */}
-
-
-
- 4. {t("page-trillion-dollar-security-consensus-title")}
-
-
{t("page-trillion-dollar-security-section-4-intro")}
-
-
-
-
-
- {t("page-trillion-dollar-security-section-4-paragraph-1")}
-
-
+ {/* Consensus Protocol section */}
+
+
+
+ 4. {t("page-trillion-dollar-security-consensus-title")}
+
+
{t("page-trillion-dollar-security-section-4-intro")}
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-4-paragraph-1")}
+
+
-
-
- {t("page-trillion-dollar-security-section-4-1-title")}
-
-
- {t("page-trillion-dollar-security-section-4-1-paragraph")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-4-1-title")}
+
+
+ {t("page-trillion-dollar-security-section-4-1-paragraph")}
+
+
-
-
- {t("page-trillion-dollar-security-section-4-2-title")}
-
-
- {t("page-trillion-dollar-security-section-4-2-paragraph")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-4-2-title")}
+
+
+ {t("page-trillion-dollar-security-section-4-2-paragraph")}
+
+
-
-
- {t("page-trillion-dollar-security-section-4-3-title")}
-
-
- {t("page-trillion-dollar-security-section-4-3-paragraph")}
-
-
- -
- {t("page-trillion-dollar-security-section-4-3-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-4-3-list-2")}
-
-
-
+
+
+ {t("page-trillion-dollar-security-section-4-3-title")}
+
+
+ {t("page-trillion-dollar-security-section-4-3-paragraph")}
+
+
+ -
+ {t("page-trillion-dollar-security-section-4-3-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-4-3-list-2")}
+
+
+
-
-
- {t("page-trillion-dollar-security-section-4-4-title")}
-
-
- {t("page-trillion-dollar-security-section-4-4-paragraph")}
-
-
- {t("page-trillion-dollar-security-section-4-5-title")}
-
-
- {t("page-trillion-dollar-security-section-4-5-paragraph")}
-
-
- -
- {t("page-trillion-dollar-security-section-4-5-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-4-5-list-2")}
-
- -
- {t("page-trillion-dollar-security-section-4-5-list-3")}
-
- -
- {t("page-trillion-dollar-security-section-4-5-list-4")}
-
-
-
+
+
+ {t("page-trillion-dollar-security-section-4-4-title")}
+
+
+ {t("page-trillion-dollar-security-section-4-4-paragraph")}
+
+
+ {t("page-trillion-dollar-security-section-4-5-title")}
+
+
+ {t("page-trillion-dollar-security-section-4-5-paragraph")}
+
+
+ -
+ {t("page-trillion-dollar-security-section-4-5-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-4-5-list-2")}
+
+ -
+ {t("page-trillion-dollar-security-section-4-5-list-3")}
+
+ -
+ {t("page-trillion-dollar-security-section-4-5-list-4")}
+
+
+
-
-
- {t("page-trillion-dollar-security-section-4-6-title")}
-
-
- {t("page-trillion-dollar-security-section-4-6-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-4-6-paragraph-2")}
-
+
+
+ {t("page-trillion-dollar-security-section-4-6-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-4-6-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-4-6-paragraph-2"
+ )}
+
+
-
-
+
- {/* Incident Response & Mitigation section */}
-
-
-
- 5. {t("page-trillion-dollar-security-incident-title")}
-
-
-
-
-
-
- {t("page-trillion-dollar-security-section-5-paragraph-1")}
-
-
- -
-
+ {/* Incident Response & Mitigation section */}
+
+
+
+ 5. {t("page-trillion-dollar-security-incident-title")}
+
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-5-paragraph-1")}
+
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-5-list-title-1"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-5-list-title-1"
+ "page-trillion-dollar-security-section-5-list-desc-1"
)}
- .
- {" "}
- {t("page-trillion-dollar-security-section-5-list-desc-1")}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-5-list-title-2"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-5-list-title-2"
+ "page-trillion-dollar-security-section-5-list-desc-2"
)}
- .
- {" "}
- {t("page-trillion-dollar-security-section-5-list-desc-2")}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-5-list-title-3"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-5-list-title-3"
+ "page-trillion-dollar-security-section-5-list-desc-3"
)}
- .
- {" "}
- {t("page-trillion-dollar-security-section-5-list-desc-3")}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-5-list-title-4"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-5-list-title-4"
+ "page-trillion-dollar-security-section-5-list-desc-4"
)}
- .
- {" "}
- {t("page-trillion-dollar-security-section-5-list-desc-4")}
-
- -
-
+
+ -
+
+ {t(
+ "page-trillion-dollar-security-section-5-list-title-5"
+ )}
+ .
+ {" "}
{t(
- "page-trillion-dollar-security-section-5-list-title-5"
+ "page-trillion-dollar-security-section-5-list-desc-5"
)}
- .
- {" "}
- {t("page-trillion-dollar-security-section-5-list-desc-5")}
-
-
+
+
+
-
-
+
- {/* Social layer and governance section */}
-
-
-
- 6. {t("page-trillion-dollar-security-social-title")}
-
-
{t("page-trillion-dollar-security-section-6-intro")}
-
-
-
-
-
- {t("page-trillion-dollar-security-section-6-paragraph-1")}
-
-
+ {/* Social layer and governance section */}
+
+
+
+ 6. {t("page-trillion-dollar-security-social-title")}
+
+
{t("page-trillion-dollar-security-section-6-intro")}
+
+
+
+
+
+ {t("page-trillion-dollar-security-section-6-paragraph-1")}
+
+
-
-
- {t("page-trillion-dollar-security-section-6-1-title")}
-
-
- {t("page-trillion-dollar-security-section-6-1-paragraph-1")}
-
- {t("page-trillion-dollar-security-section-6-1-paragraph-2")}
-
-
- -
- {t("page-trillion-dollar-security-section-6-1-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-6-1-list-2")}
-
- -
- {t("page-trillion-dollar-security-section-6-1-list-3")}
-
-
-
- {t("page-trillion-dollar-security-section-6-1-paragraph-3")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-6-1-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-6-1-paragraph-1"
+ )}
+
+ {t(
+ "page-trillion-dollar-security-section-6-1-paragraph-2"
+ )}
+
+
+ -
+ {t("page-trillion-dollar-security-section-6-1-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-6-1-list-2")}
+
+ -
+ {t("page-trillion-dollar-security-section-6-1-list-3")}
+
+
+
+ {t(
+ "page-trillion-dollar-security-section-6-1-paragraph-3"
+ )}
+
+
-
-
- {t("page-trillion-dollar-security-section-6-2-title")}
-
-
- {t("page-trillion-dollar-security-section-6-2-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-6-2-paragraph-2")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-6-2-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-6-2-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-6-2-paragraph-2"
+ )}
+
+
-
-
- {t("page-trillion-dollar-security-section-6-3-title")}
-
-
- {t("page-trillion-dollar-security-section-6-3-paragraph")}
-
-
+
+
+ {t("page-trillion-dollar-security-section-6-3-title")}
+
+
+ {t("page-trillion-dollar-security-section-6-3-paragraph")}
+
+
-
-
- {t("page-trillion-dollar-security-section-6-4-title")}
-
-
- {t("page-trillion-dollar-security-section-6-4-paragraph-1")}
-
-
- {t("page-trillion-dollar-security-section-6-4-paragraph-2")}
-
+
+
+ {t("page-trillion-dollar-security-section-6-4-title")}
+
+
+ {t(
+ "page-trillion-dollar-security-section-6-4-paragraph-1"
+ )}
+
+
+ {t(
+ "page-trillion-dollar-security-section-6-4-paragraph-2"
+ )}
+
+
-
-
+
+
-
-
+
+ >
)
}
diff --git a/app/[locale]/wallets/_components/wallets.tsx b/app/[locale]/wallets/_components/wallets.tsx
deleted file mode 100644
index 78f942328d4..00000000000
--- a/app/[locale]/wallets/_components/wallets.tsx
+++ /dev/null
@@ -1,438 +0,0 @@
-"use client"
-
-import { ComponentPropsWithRef } from "react"
-import { useLocale } from "next-intl"
-
-import { PageWithContributorsProps } from "@/lib/types"
-
-import Callout from "@/components/Callout"
-import Card from "@/components/Card"
-import CardList from "@/components/CardList"
-import FeedbackCard from "@/components/FeedbackCard"
-import FileContributors from "@/components/FileContributors"
-import HorizontalCard from "@/components/HorizontalCard"
-import { Image } from "@/components/Image"
-import ListenToPlayer from "@/components/ListenToPlayer"
-import MainArticle from "@/components/MainArticle"
-import PageHero from "@/components/PageHero"
-import { StandaloneQuizWidget } from "@/components/Quiz/QuizWidget"
-import { Simulator } from "@/components/Simulator"
-import { SIMULATOR_ID } from "@/components/Simulator/constants"
-import Translation from "@/components/Translation"
-import { ButtonLink } from "@/components/ui/buttons/Button"
-import { Divider } from "@/components/ui/divider"
-
-import { walletOnboardingSimData } from "@/data/WalletSimulatorData"
-
-import { useTranslation } from "@/hooks/useTranslation"
-import { usePathname } from "@/i18n/routing"
-import DappsImage from "@/public/images/doge-computer.png"
-import ETHImage from "@/public/images/eth-logo.png"
-import FindWalletImage from "@/public/images/wallets/find-wallet.png"
-import HeroImage from "@/public/images/wallets/wallet-hero.png"
-
-export const StyledCard = (props: ComponentPropsWithRef
) => (
-
-)
-
-const WalletsPage = ({
- contributors,
- lastEditLocaleTimestamp,
-}: PageWithContributorsProps) => {
- const pathname = usePathname()
- const locale = useLocale()
- const { t } = useTranslation("page-wallets")
-
- const heroContent = {
- title: t("page-wallets-title"),
- header: t("page-wallets-slogan"),
- subtitle: t("page-wallets-subtitle"),
- image: HeroImage,
- alt: t("page-wallets-alt"),
- // TODO: remove conditional after soft launch
- buttons:
- locale === "en"
- ? [
- {
- href: "/wallets/find-wallet/",
- content: t("page-wallets-find-wallet-link"),
- matomo: {
- eventCategory: "Header buttons",
- eventAction: "click",
- eventName: "Find_wallet",
- },
- },
- {
- href: `#${SIMULATOR_ID}`,
- content: "How to use a wallet",
- matomo: {
- eventCategory: "Header buttons",
- eventAction: "click",
- eventName: "How_to_use_wallet",
- },
- variant: "outline" as const,
- },
- ]
- : [
- {
- href: "/wallets/find-wallet/",
- content: t("page-wallets-find-wallet-link"),
- matomo: {
- eventCategory: "Header button",
- eventAction: "click",
- eventName: "Find_wallet",
- },
- },
- ],
- }
-
- const cards = [
- {
- emoji: ":dollar:",
- title: t("page-wallets-manage-funds"),
- description: (
-
- ),
- },
- {
- emoji: ":frame_with_picture:",
- title: t("page-wallets-your-ethereum-account"),
- description: (
-
- ),
- },
- {
- emoji: ":bust_in_silhouette:",
- title: t("page-wallets-your-login"),
- description: (
-
- ),
- },
- ]
-
- const types = [
- {
- emoji: ":cd:",
- description: ,
- },
- {
- emoji: ":mobile_phone:",
- description: ,
- },
- {
- emoji: ":globe_with_meridians:",
- description: ,
- },
- {
- emoji: ":globe_with_meridians:",
- description: (
-
- ),
- },
- {
- emoji: ":desktop_computer:",
- description: ,
- },
- ]
-
- const articles = [
- {
- title: t("page-wallets-protecting-yourself"),
- description: "MyCrypto",
- link: "https://support.mycrypto.com/staying-safe/protecting-yourself-and-your-funds",
- customEventOptions: {
- eventCategory: "Link",
- eventAction: "Clicked_external",
- eventName: "protecting_yourself",
- },
- },
- {
- title: t("page-wallets-keys-to-safety"),
- description: t("page-wallets-blog"),
- link: "https://www.coinbase.com/learn/crypto-basics/how-to-secure-crypto",
- customEventOptions: {
- eventCategory: "Link",
- eventAction: "Clicked_external",
- eventName: "the_keys_to_keeping_crypto_safe",
- },
- },
- ]
-
- const guides = [
- {
- title: t("additional-reading-how-to-create-an-ethereum-account"),
- link: "/guides/how-to-create-an-ethereum-account/",
- customEventOptions: {
- eventCategory: "Link",
- eventAction: "Clicked",
- eventName: "Create_eth_acc",
- },
- },
- {
- title: t("additional-reading-how-to-use-a-wallet"),
- link: "/guides/how-to-use-a-wallet/",
- customEventOptions: {
- eventCategory: "Link",
- eventAction: "Clicked",
- eventName: "How_to_use_wallet",
- },
- },
- ]
-
- return (
-
-
-
-
-
-
-
-
-
- {t("page-wallets-whats-a-wallet")}
-
-
-
-
-
- {t("page-wallets-description")}
-
-
- {t("page-wallets-desc-2")}
-
-
-
-
-
- {t("page-wallets-desc-3")}
-
-
- {t("page-wallets-desc-4")}
-
-
-
-
-
- {cards.map((card, idx) => (
-
- ))}
-
-
-
-
-
-
-
- {t("page-wallets-accounts-addresses")}
-
-
- {t("page-wallets-accounts-addresses-desc")}
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
-
-
- {t("page-wallets-most-wallets")}
-
-
-
-
- {t("page-wallets-types")}
-
-
- {t("page-wallets-types-desc")}
-
-
- {types.map((type, idx) => (
-
- ))}
-
-
-
-
- {locale === "en" ? (
-
-
-
- Interactive tutorial
-
-
- How to use a wallet
-
-
-
- ) : (
-
-
-
-
- {t("page-wallets-features-title")}
-
-
- {t("page-wallets-features-desc")}
-
-
- {t("page-wallets-find-wallet-btn")}
-
-
-
-
-
- )}
-
-
-
-
- {t("page-wallets-stay-safe")}
-
-
-
-
-
-
-
}
- description={t("page-wallets-seed-phrase-desc")}
- emojiClassName="text-2xl"
- className="items-start"
- >
-
- {t("page-wallets-seed-phrase-example")}
-
-
-
- {t("page-wallets-seed-phrase-snippet")}
-
-
-
- {t("page-wallets-seed-phrase-write-down")}
-
-
-
-
-
-
-
-
- {t("page-wallets-tips")}
-
-
{t("page-wallets-tips-community")}
-
-
-
-
-
-
-
-
- {t("page-wallets-explore")}
-
-
-
-
-
- {t("page-wallets-get-some-btn")}
-
-
-
-
-
-
- {t("page-wallets-more-on-dapps-btn")}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
-}
-
-export default WalletsPage
diff --git a/app/[locale]/wallets/find-wallet/page-jsonld.tsx b/app/[locale]/wallets/find-wallet/page-jsonld.tsx
new file mode 100644
index 00000000000..5661ee7c4ee
--- /dev/null
+++ b/app/[locale]/wallets/find-wallet/page-jsonld.tsx
@@ -0,0 +1,152 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang, WalletData } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function FindWalletPageJsonLD({
+ locale,
+ wallets,
+ contributors,
+}: {
+ locale: Lang | undefined
+ wallets: WalletData[]
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-find-wallet",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/wallets/find-wallet/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Find Wallet page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-find-wallet-meta-title"),
+ description: t("page-find-wallet-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: "Wallets",
+ item: normalizeUrlForJsonLd(locale, "/wallets/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 3,
+ name: t("page-find-wallet-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the wallet finder article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-find-wallet-title"),
+ description: t("page-find-wallet-meta-description"),
+ image: "https://ethereum.org/images/wallets/wallet-hero.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ contributor: contributorList,
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Wallet Finder",
+ description:
+ "Tool to find and compare Ethereum wallets based on features and requirements",
+ },
+ }
+
+ // JSON-LD for the wallet directory list
+ const walletDirectoryJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "ItemList",
+ name: "Ethereum Wallet Directory",
+ description:
+ "Comprehensive list of Ethereum wallets with features and comparisons",
+ numberOfItems: wallets.length,
+ itemListElement: wallets.slice(0, 20).map((wallet, index) => ({
+ "@type": "ListItem",
+ position: index + 1,
+ item: {
+ "@type": "Product",
+ additionalType: "https://schema.org/SoftwareApplication",
+ name: wallet.name,
+ description: `${wallet.name} Ethereum wallet`,
+ category: "Cryptocurrency Wallet",
+ url: wallet.url,
+ applicationCategory: "Finance",
+ operatingSystem: "Multiple platforms",
+ },
+ })),
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/wallets/find-wallet/page.tsx b/app/[locale]/wallets/find-wallet/page.tsx
index e5a41bf6636..a11dd7ec8be 100644
--- a/app/[locale]/wallets/find-wallet/page.tsx
+++ b/app/[locale]/wallets/find-wallet/page.tsx
@@ -5,13 +5,14 @@ import {
setRequestLocale,
} from "next-intl/server"
-import { Lang } from "@/lib/types"
+import { CommitHistory, Lang } from "@/lib/types"
import Breadcrumbs from "@/components/Breadcrumbs"
import FindWalletProductTable from "@/components/FindWalletProductTable/lazy"
import I18nProvider from "@/components/I18nProvider"
import MainArticle from "@/components/MainArticle"
+import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
import {
@@ -20,6 +21,8 @@ import {
getSupportedLocaleWallets,
} from "@/lib/utils/wallets"
+import FindWalletPageJsonLD from "./page-jsonld"
+
const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const { locale } = await params
const t = await getTranslations({
@@ -49,22 +52,37 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
)
const messages = pick(allMessages, requiredNamespaces)
+ const commitHistoryCache: CommitHistory = {}
+ const { contributors } = await getAppPageContributorInfo(
+ "wallets/find-wallet",
+ locale as Lang,
+ commitHistoryCache
+ )
+
return (
-
-
-
-
-
- {t("page-find-wallet-title")}
-
-
- {t("page-find-wallet-description")}
-
-
-
-
-
-
+ <>
+
+
+
+
+
+
+
+ {t("page-find-wallet-title")}
+
+
+ {t("page-find-wallet-description")}
+
+
+
+
+
+
+ >
)
}
diff --git a/app/[locale]/wallets/page-jsonld.tsx b/app/[locale]/wallets/page-jsonld.tsx
new file mode 100644
index 00000000000..787b025bc1c
--- /dev/null
+++ b/app/[locale]/wallets/page-jsonld.tsx
@@ -0,0 +1,140 @@
+import { getTranslations } from "next-intl/server"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function WalletsPageJsonLD({
+ locale,
+ types,
+ lastEditLocaleTimestamp,
+ contributors,
+}) {
+ const t = await getTranslations({
+ namespace: "page-find-wallet",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/wallets/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the Wallets page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-wallets-meta-title"),
+ description: t("page-wallets-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: t("page-wallets-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the wallets guide article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-wallets-title"),
+ description: t("page-wallets-meta-description"),
+ image: "https://ethereum.org/images/wallets/wallet-hero.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ contributor: contributorList,
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum Wallets",
+ description:
+ "Complete guide to Ethereum wallets, types, features, and how to use them safely",
+ },
+ dateModified: lastEditLocaleTimestamp,
+ }
+
+ // JSON-LD for the wallet types list
+ const walletTypesJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "ItemList",
+ name: "Ethereum Wallet Types",
+ description: "Different types of Ethereum wallets available",
+ itemListElement: types.map((type, index) => ({
+ "@type": "ListItem",
+ position: index + 1,
+ item: {
+ "@type": "Product",
+ additionalType: "https://schema.org/SoftwareApplication",
+ category: "Cryptocurrency Wallet",
+ name: `Ethereum ${type.emoji === ":cd:" ? "Hardware" : type.emoji === ":mobile_phone:" ? "Mobile" : type.emoji === ":desktop_computer:" ? "Desktop" : "Web"} Wallet`,
+ description:
+ typeof type.description === "string"
+ ? type.description
+ : `${type.emoji === ":cd:" ? "Hardware" : type.emoji === ":mobile_phone:" ? "Mobile" : type.emoji === ":desktop_computer:" ? "Desktop" : "Web"} wallet for Ethereum`,
+ },
+ })),
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/wallets/page.tsx b/app/[locale]/wallets/page.tsx
index 566008b1483..bf5ff76fe70 100644
--- a/app/[locale]/wallets/page.tsx
+++ b/app/[locale]/wallets/page.tsx
@@ -1,3 +1,4 @@
+import { ComponentPropsWithRef } from "react"
import { pick } from "lodash"
import {
getMessages,
@@ -7,16 +8,47 @@ import {
import type { CommitHistory, Lang } from "@/lib/types"
+import Callout from "@/components/Callout"
+import Card from "@/components/Card"
+import CardList from "@/components/CardList"
+import FeedbackCard from "@/components/FeedbackCard"
+import FileContributors from "@/components/FileContributors"
+import HorizontalCard from "@/components/HorizontalCard"
import I18nProvider from "@/components/I18nProvider"
+import { Image } from "@/components/Image"
+import ListenToPlayer from "@/components/ListenToPlayer"
+import MainArticle from "@/components/MainArticle"
+import PageHero from "@/components/PageHero"
+import { StandaloneQuizWidget } from "@/components/Quiz/QuizWidget"
+import { Simulator } from "@/components/Simulator"
+import { SIMULATOR_ID } from "@/components/Simulator/constants"
+import Translation from "@/components/Translation"
+import { ButtonLink } from "@/components/ui/buttons/Button"
+import { Divider } from "@/components/ui/divider"
import { getAppPageContributorInfo } from "@/lib/utils/contributors"
import { getMetadata } from "@/lib/utils/metadata"
import { getRequiredNamespacesForPage } from "@/lib/utils/translations"
-import WalletsPage from "./_components/wallets"
+import { walletOnboardingSimData } from "@/data/WalletSimulatorData"
+
+import WalletsPageJsonLD from "./page-jsonld"
+
+import DappsImage from "@/public/images/doge-computer.png"
+import ETHImage from "@/public/images/eth-logo.png"
+import FindWalletImage from "@/public/images/wallets/find-wallet.png"
+import HeroImage from "@/public/images/wallets/wallet-hero.png"
+
+const StyledCard = (props: ComponentPropsWithRef) => (
+
+)
const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
const { locale } = await params
+ const t = await getTranslations({ locale, namespace: "page-wallets" })
setRequestLocale(locale)
@@ -33,12 +65,403 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
commitHistoryCache
)
+ const heroContent = {
+ title: t("page-wallets-title"),
+ header: t("page-wallets-slogan"),
+ subtitle: t("page-wallets-subtitle"),
+ image: HeroImage,
+ alt: t("page-wallets-alt"),
+ // TODO: remove conditional after soft launch
+ buttons:
+ locale === "en"
+ ? [
+ {
+ href: "/wallets/find-wallet/",
+ content: t("page-wallets-find-wallet-link"),
+ matomo: {
+ eventCategory: "Header buttons",
+ eventAction: "click",
+ eventName: "Find_wallet",
+ },
+ },
+ {
+ href: `#${SIMULATOR_ID}`,
+ content: "How to use a wallet",
+ matomo: {
+ eventCategory: "Header buttons",
+ eventAction: "click",
+ eventName: "How_to_use_wallet",
+ },
+ variant: "outline" as const,
+ },
+ ]
+ : [
+ {
+ href: "/wallets/find-wallet/",
+ content: t("page-wallets-find-wallet-link"),
+ matomo: {
+ eventCategory: "Header button",
+ eventAction: "click",
+ eventName: "Find_wallet",
+ },
+ },
+ ],
+ }
+
+ const cards = [
+ {
+ emoji: ":dollar:",
+ title: t("page-wallets-manage-funds"),
+ description: (
+
+ ),
+ },
+ {
+ emoji: ":frame_with_picture:",
+ title: t("page-wallets-your-ethereum-account"),
+ description: (
+
+ ),
+ },
+ {
+ emoji: ":bust_in_silhouette:",
+ title: t("page-wallets-your-login"),
+ description: (
+
+ ),
+ },
+ ]
+
+ const types = [
+ {
+ emoji: ":cd:",
+ description: ,
+ },
+ {
+ emoji: ":mobile_phone:",
+ description: ,
+ },
+ {
+ emoji: ":globe_with_meridians:",
+ description: ,
+ },
+ {
+ emoji: ":globe_with_meridians:",
+ description: (
+
+ ),
+ },
+ {
+ emoji: ":desktop_computer:",
+ description: ,
+ },
+ ]
+
+ const articles = [
+ {
+ title: t("page-wallets-protecting-yourself"),
+ description: "MyCrypto",
+ link: "https://support.mycrypto.com/staying-safe/protecting-yourself-and-your-funds",
+ customEventOptions: {
+ eventCategory: "Link",
+ eventAction: "Clicked_external",
+ eventName: "protecting_yourself",
+ },
+ },
+ {
+ title: t("page-wallets-keys-to-safety"),
+ description: t("page-wallets-blog"),
+ link: "https://www.coinbase.com/learn/crypto-basics/how-to-secure-crypto",
+ customEventOptions: {
+ eventCategory: "Link",
+ eventAction: "Clicked_external",
+ eventName: "the_keys_to_keeping_crypto_safe",
+ },
+ },
+ ]
+
+ const guides = [
+ {
+ title: t("additional-reading-how-to-create-an-ethereum-account"),
+ link: "/guides/how-to-create-an-ethereum-account/",
+ customEventOptions: {
+ eventCategory: "Link",
+ eventAction: "Clicked",
+ eventName: "Create_eth_acc",
+ },
+ },
+ {
+ title: t("additional-reading-how-to-use-a-wallet"),
+ link: "/guides/how-to-use-a-wallet/",
+ customEventOptions: {
+ eventCategory: "Link",
+ eventAction: "Clicked",
+ eventName: "How_to_use_wallet",
+ },
+ },
+ ]
+
return (
-
+
+
+
+
+
+
+
+
+
+ {t("page-wallets-whats-a-wallet")}
+
+
+
+
+
+ {t("page-wallets-description")}
+
+
+ {t("page-wallets-desc-2")}
+
+
+
+
+
+ {t("page-wallets-desc-3")}
+
+
+ {t("page-wallets-desc-4")}
+
+
+
+
+
+ {cards.map((card, idx) => (
+
+ ))}
+
+
+
+
+
+
+
+ {t("page-wallets-accounts-addresses")}
+
+
+ {t("page-wallets-accounts-addresses-desc")}
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
+ {t("page-wallets-most-wallets")}
+
+
+
+
+ {t("page-wallets-types")}
+
+
+ {t("page-wallets-types-desc")}
+
+
+ {types.map((type, idx) => (
+
+ ))}
+
+
+
+
+ {locale === "en" ? (
+
+
+
+ Interactive tutorial
+
+
+ How to use a wallet
+
+
+
+ ) : (
+
+
+
+
+ {t("page-wallets-features-title")}
+
+
+ {t("page-wallets-features-desc")}
+
+
+ {t("page-wallets-find-wallet-btn")}
+
+
+
+
+
+ )}
+
+
+
+
+ {t("page-wallets-stay-safe")}
+
+
+
+
+
+
+
+ }
+ description={t("page-wallets-seed-phrase-desc")}
+ emojiClassName="text-2xl"
+ className="items-start"
+ >
+
+ {t("page-wallets-seed-phrase-example")}
+
+
+
+ {t("page-wallets-seed-phrase-snippet")}
+
+
+
+ {t("page-wallets-seed-phrase-write-down")}
+
+
+
+
+
+
+
+
+ {t("page-wallets-tips")}
+
+
+ {t("page-wallets-tips-community")}
+
+
+
+
+
+
+
+
+
+ {t("page-wallets-explore")}
+
+
+
+
+
+ {t("page-wallets-get-some-btn")}
+
+
+
+
+
+
+ {t("page-wallets-more-on-dapps-btn")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
diff --git a/app/[locale]/what-is-ethereum/page-jsonld.tsx b/app/[locale]/what-is-ethereum/page-jsonld.tsx
new file mode 100644
index 00000000000..6bc74e97e6e
--- /dev/null
+++ b/app/[locale]/what-is-ethereum/page-jsonld.tsx
@@ -0,0 +1,178 @@
+import { getTranslations } from "next-intl/server"
+
+import { FileContributor, Lang } from "@/lib/types"
+
+import PageJsonLD from "@/components/PageJsonLD"
+
+import { normalizeUrlForJsonLd } from "@/lib/utils/url"
+
+export default async function WhatIsEthereumPageJsonLD({
+ locale,
+ lastEditLocaleTimestamp,
+ contributors,
+}: {
+ locale: Lang | undefined
+ lastEditLocaleTimestamp: string
+ contributors: FileContributor[]
+}) {
+ const t = await getTranslations({
+ namespace: "page-what-is-ethereum",
+ })
+
+ const url = normalizeUrlForJsonLd(locale, `/what-is-ethereum/`)
+
+ const contributorList = contributors.map((contributor) => ({
+ "@type": "Person",
+ name: contributor.login,
+ url: contributor.html_url,
+ }))
+
+ // JSON-LD structured data for the What is Ethereum page
+ const webPageJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "WebPage",
+ "@id": url,
+ name: t("page-what-is-ethereum-meta-title"),
+ description: t("page-what-is-ethereum-meta-description"),
+ url: url,
+ inLanguage: locale,
+ contributor: contributorList,
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ breadcrumb: {
+ "@type": "BreadcrumbList",
+ itemListElement: [
+ {
+ "@type": "ListItem",
+ position: 1,
+ name: "Home",
+ item: normalizeUrlForJsonLd(locale, "/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 2,
+ name: "Learn",
+ item: normalizeUrlForJsonLd(locale, "/learn/"),
+ },
+ {
+ "@type": "ListItem",
+ position: 3,
+ name: t("page-what-is-ethereum-meta-title"),
+ item: url,
+ },
+ ],
+ },
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ }
+
+ // JSON-LD for the what is ethereum article content
+ const articleJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "Article",
+ headline: t("page-what-is-ethereum-title"),
+ description: t("page-what-is-ethereum-meta-description"),
+ image: "https://ethereum.org/images/what-is-ethereum.png",
+ author: [
+ {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ ],
+ publisher: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ },
+ contributor: contributorList,
+ reviewedBy: {
+ "@type": "Organization",
+ name: "ethereum.org",
+ url: "https://ethereum.org",
+ logo: {
+ "@type": "ImageObject",
+ url: "https://ethereum.org/images/eth-home-icon.png",
+ },
+ },
+ about: {
+ "@type": "Thing",
+ name: "Ethereum",
+ description:
+ "Comprehensive guide to Ethereum, its network, capabilities, and how it works",
+ },
+ dateModified: lastEditLocaleTimestamp,
+ }
+
+ // JSON-LD for FAQ-style content covering common Ethereum questions
+ const faqJsonLd = {
+ "@context": "https://schema.org",
+ "@type": "FAQPage",
+ mainEntity: [
+ {
+ "@type": "Question",
+ name: "What is Ethereum?",
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: t("page-what-is-ethereum-hero-description-1").replace(
+ /<[^>]*>/g,
+ ""
+ ),
+ },
+ },
+ {
+ "@type": "Question",
+ name: "How does the Ethereum network work?",
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: "Ethereum is a decentralized network of computers that work together to run applications and store data without a central authority.",
+ },
+ },
+ {
+ "@type": "Question",
+ name: "What is Ether (ETH)?",
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: "Ether is the native cryptocurrency of the Ethereum network, used to pay for transactions and computational services.",
+ },
+ },
+ {
+ "@type": "Question",
+ name: "What can you do with Ethereum?",
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: "Ethereum enables decentralized applications, smart contracts, financial services, gaming, collectibles, and much more.",
+ },
+ },
+ {
+ "@type": "Question",
+ name: "How is Ethereum different from Bitcoin?",
+ acceptedAnswer: {
+ "@type": "Answer",
+ text: "While Bitcoin is primarily digital money, Ethereum is a programmable blockchain that can run applications and smart contracts.",
+ },
+ },
+ ],
+ }
+
+ return (
+
+ )
+}
diff --git a/app/[locale]/what-is-ethereum/page.tsx b/app/[locale]/what-is-ethereum/page.tsx
index f18697cbaa7..dadf2c1b9a0 100644
--- a/app/[locale]/what-is-ethereum/page.tsx
+++ b/app/[locale]/what-is-ethereum/page.tsx
@@ -32,6 +32,8 @@ import { getDirection } from "@/lib/utils/direction"
import { getMetadata } from "@/lib/utils/metadata"
import { screens } from "@/lib/utils/screen"
+import WhatIsEthereumPageJsonLD from "./page-jsonld"
+
import contributionBanner from "@/public/images/doge-computer.png"
import whatBanner from "@/public/images/eth.png"
import howBanner from "@/public/images/hackathon_transparent.png"
@@ -149,958 +151,1001 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => {
return parts.length > 1 ? parts[1] : ""
}
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-1", {
- strong: Strong,
- })}
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-2", {
- a: (chunks) => {chunks},
- })}
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-3", {
- strong: Strong,
- })}
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-4", {
- strong: Strong,
- })}
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-5", {
- strong: Strong,
- })}
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-6", {
- millions: (chunks) => (
-
- {chunks}
-
- ),
- billions: (chunks) => (
-
- {chunks}
-
- ),
- trillions: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
-
- {t.rich("page-what-is-ethereum-ethereum-intro-7", {
- strong: Strong,
- })}
-
-
-
-
-
-
-
-
- {tocItems[1].title}
-
-
-
- {t.rich("page-what-is-ethereum-network-intro-1", {
- strong: Strong,
- })}
-
-
-
- {t.rich("page-what-is-ethereum-network-intro-2", {
- strong: Strong,
- })}
-
-
-
- {t.rich("page-what-is-ethereum-network-intro-3", {
- strong: Strong,
- })}
-
-
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-network-censorship-title")}
-
-
-
- {t("page-what-is-ethereum-network-censorship-desc-1")}
-
-
- {t("page-what-is-ethereum-network-censorship-desc-2")}
-
-
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-network-security-title")}
-
-
- {t("page-what-is-ethereum-network-security-desc-1")}
- {t("page-what-is-ethereum-network-security-desc-2")}
-
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-network-reliability-title")}
-
-
-
- {t.rich(
- "page-what-is-ethereum-network-reliability-desc-1",
- {
- a: (chunks) => {chunks},
- }
- )}
-
-
- {t("page-what-is-ethereum-network-reliability-desc-2")}
-
-
-
-
-
+ <>
+
-
-
- {t("page-what-is-ethereum-network-layer2-title")}
-
-
-
-
{t("page-what-is-ethereum-network-layer2-desc-1")}
+
+
-
- {t.rich("page-what-is-ethereum-network-layer2-desc-2", {
- optimism: (chunks) => (
- {chunks}
- ),
- arbitrum: (chunks) => (
- {chunks}
- ),
- zksync: (chunks) => (
- {chunks}
- ),
- base: (chunks) => (
- {chunks}
- ),
- })}
-
-
-
+
+
+
-
- {t("page-what-is-ethereum-network-learn-more")}
-
-
+
+
-
-
-
-
- {tocItems[2].title}
-
-
+
-
-
{t("page-what-is-ethereum-ether-intro-1")}
-
- {t.rich("page-what-is-ethereum-ether-intro-2", {
- strong: Strong,
- })}
-
-
- {t.rich("page-what-is-ethereum-ether-intro-3", {
- strong: Strong,
- })}
-
+
+
- {t.rich("page-what-is-ethereum-ether-intro-4", {
+ {t.rich("page-what-is-ethereum-ethereum-intro-1", {
strong: Strong,
})}
- {t.rich("page-what-is-ethereum-ether-intro-5", {
- strong: Strong,
+ {t.rich("page-what-is-ethereum-ethereum-intro-2", {
+ a: (chunks) => {chunks},
})}
- {t("page-what-is-ethereum-ether-intro-6")}
-
-
-
- {t("page-what-is-ethereum-ether-learn-more")}
-
-
-
-
-
-
-
- {tocItems[3].title}
-
-
-
-
- {t.rich("page-what-is-ethereum-how-intro-1", {
+ {t.rich("page-what-is-ethereum-ethereum-intro-3", {
strong: Strong,
})}
-
{t("page-what-is-ethereum-how-intro-2")}
- {t.rich("page-what-is-ethereum-how-intro-3", {
+ {t.rich("page-what-is-ethereum-ethereum-intro-4", {
strong: Strong,
- a: (chunks) => (
- {chunks}
- ),
})}
-
{t("page-what-is-ethereum-how-intro-4")}
-
{t("page-what-is-ethereum-how-intro-5")}
-
- {t("page-what-is-ethereum-how-example-1-title")}
-
-
-
- {t("page-what-is-ethereum-how-example-1-step-1")}
-
-
- {t("page-what-is-ethereum-how-example-1-step-2")}
-
-
- {t("page-what-is-ethereum-how-example-1-step-3")}
-
-
- {t("page-what-is-ethereum-how-example-1-step-4")}
-
-
- {t("page-what-is-ethereum-how-example-1-step-5")}
-
-
- {t("page-what-is-ethereum-how-example-1-step-6")}
-
-
-
- {t("page-what-is-ethereum-how-example-2-title")}
-
-
-
- {t("page-what-is-ethereum-how-example-2-step-1")}
-
-
- {t("page-what-is-ethereum-how-example-2-step-2")}
-
-
- {t("page-what-is-ethereum-how-example-2-step-3")}
-
-
- {t("page-what-is-ethereum-how-example-2-step-4")}
-
-
- {t("page-what-is-ethereum-how-example-2-step-5")}
-
-
-
{t("page-what-is-ethereum-how-outro-1")}
- {t.rich("page-what-is-ethereum-how-outro-2", {
+ {t.rich("page-what-is-ethereum-ethereum-intro-5", {
strong: Strong,
})}
-
-
- {t("page-what-is-ethereum-how-learn-more-1")}
-
-
- {t("page-what-is-ethereum-how-learn-more-2")}
-
-
-
-
-
-
-
-
- {tocItems[4].title}
-
-
-
{t("page-what-is-ethereum-what-intro-1")}
- {t.rich("page-what-is-ethereum-what-intro-2", {
- strong: Strong,
- insurance: (chunks) => (
-
+ {t.rich("page-what-is-ethereum-ethereum-intro-6", {
+ millions: (chunks) => (
+
{chunks}
),
- payment: (chunks) => (
-
+ billions: (chunks) => (
+
{chunks}
),
- aid: (chunks) => (
-
+ trillions: (chunks) => (
+
{chunks}
),
})}
-
{t("page-what-is-ethereum-what-intro-3")}
-
{t("page-what-is-ethereum-what-intro-4")}
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-what-consumers-title")}
-
-
- {t("page-what-is-ethereum-what-consumers-desc-1")}
- {t("page-what-is-ethereum-what-consumers-desc-2")}
-
-
- {t.rich(
- "page-what-is-ethereum-what-consumers-benefit-1",
- {
- strong: Strong,
- }
- )}
-
-
- {t.rich(
- "page-what-is-ethereum-what-consumers-benefit-2",
- {
- strong: Strong,
- }
- )}
-
-
- {t.rich(
- "page-what-is-ethereum-what-consumers-benefit-3",
- {
- strong: Strong,
- }
- )}
-
-
- {t("page-what-is-ethereum-what-consumers-benefit-4")}
-
-
-
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-what-businesses-title")}
-
-
-
-
- {t("page-what-is-ethereum-what-businesses-benefit-1")}
-
-
- {t.rich(
- "page-what-is-ethereum-what-businesses-benefit-2",
- {
- strong: Strong,
- }
- )}
-
-
- {t("page-what-is-ethereum-what-businesses-benefit-3")}
-
-
-
- {t.rich("page-what-is-ethereum-what-businesses-example", {
- a: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
-
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-what-governments-title")}
-
-
- {t("page-what-is-ethereum-what-governments-intro")}
-
-
- {t.rich(
- "page-what-is-ethereum-what-governments-benefit-1",
- {
- strong: Strong,
- }
- )}
-
-
- {t.rich(
- "page-what-is-ethereum-what-governments-benefit-2",
- {
- strong: Strong,
- }
- )}
-
-
+
+ {t.rich("page-what-is-ethereum-ethereum-intro-7", {
+ strong: Strong,
+ })}
+
+
+
+
+
+
+
+
+ {tocItems[1].title}
+
+
+
+ {t.rich("page-what-is-ethereum-network-intro-1", {
+ strong: Strong,
+ })}
+
+
+
+ {t.rich("page-what-is-ethereum-network-intro-2", {
+ strong: Strong,
+ })}
+
+
+
+ {t.rich("page-what-is-ethereum-network-intro-3", {
+ strong: Strong,
+ })}
+
+
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-network-censorship-title")}
+
+
+
+ {t("page-what-is-ethereum-network-censorship-desc-1")}
+
+
+ {t("page-what-is-ethereum-network-censorship-desc-2")}
+
+
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-network-security-title")}
+
+
+
+ {t("page-what-is-ethereum-network-security-desc-1")}
+
+
+ {t("page-what-is-ethereum-network-security-desc-2")}
+
+
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-network-reliability-title")}
+
+
+
{t.rich(
- "page-what-is-ethereum-what-governments-benefit-3",
+ "page-what-is-ethereum-network-reliability-desc-1",
{
- strong: Strong,
+ a: (chunks) => {chunks},
}
)}
-
-
-
- {t.rich(
- "page-what-is-ethereum-what-governments-example-1",
- {
- a: (chunks) => (
-
- {chunks}
-
- ),
- }
- )}
-
-
- {t("page-what-is-ethereum-what-governments-example-2")}
-
-
-
-
-
-
- {/* // TODO: Re-enable when page ready */}
- {/*
- {t("page-what-is-ethereum-what-learn-more")}
- */}
-
-
-
-
-
-
- {tocItems[5].title}
-
-
-
{t("page-what-is-ethereum-start-intro-1")}
-
{t("page-what-is-ethereum-start-intro-2")}
-
-
-
-
-
-
- {t("page-what-is-ethereum-start-individuals-title")}
-
-
-
-
-
- {t("page-what-is-ethereum-start-individuals-desc-1")}
-
-
-
-
- {t.rich("page-what-is-ethereum-start-individuals-desc-3", {
- zerion: (chunks) => (
- {chunks}
- ),
- rainbow: (chunks) => (
- {chunks}
- ),
- coinbase: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
-
-
-
- {t("page-what-is-ethereum-start-individuals-step-1")}
-
-
- {t("page-what-is-ethereum-start-individuals-step-2")}
-
-
- {t.rich(
- "page-what-is-ethereum-start-individuals-step-3",
- {
- zora: (chunks) => (
- {chunks}
- ),
- uniswap: (chunks) => (
-
- {chunks}
-
- ),
- farcaster: (chunks) => (
- {chunks}
- ),
- }
- )}
-
-
+
+
+ {t("page-what-is-ethereum-network-reliability-desc-2")}
+
+
+
+
+
- {t("page-what-is-ethereum-start-individuals-desc-4")}
- {t("page-what-is-ethereum-start-individuals-desc-5")}
-
+
+
+ {t("page-what-is-ethereum-network-layer2-title")}
+
-
-
- {t("page-what-is-ethereum-start-individuals-cta-1")}
-
-
- {t("page-what-is-ethereum-start-individuals-cta-2")}
-
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-start-developers-title")}
-
-
-
{t("page-what-is-ethereum-start-developers-desc-1")}
-
- {t.rich("page-what-is-ethereum-start-developers-desc-2", {
- a: (chunks) => (
- {chunks}
- ),
- })}
-
+
{t("page-what-is-ethereum-network-layer2-desc-1")}
+
- {t.rich("page-what-is-ethereum-start-developers-desc-3", {
- hardhat: (chunks) => (
- {chunks}
- ),
- foundry: (chunks) => (
- {chunks}
+ {t.rich("page-what-is-ethereum-network-layer2-desc-2", {
+ optimism: (chunks) => (
+ {chunks}
),
- ethers: (chunks) => (
- {chunks}
+ arbitrum: (chunks) => (
+ {chunks}
),
- thirdweb: (chunks) => (
- {chunks}
+ zksync: (chunks) => (
+ {chunks}
),
- moralis: (chunks) => (
- {chunks}
+ base: (chunks) => (
+ {chunks}
),
})}
-
{t("page-what-is-ethereum-start-developers-desc-4")}
-
- {t("page-what-is-ethereum-start-developers-cta")}
-
-
-
-
-
-
-
- {t("page-what-is-ethereum-start-business-title")}
-
-
-
-
{t("page-what-is-ethereum-start-business-desc-1")}
-
{t("page-what-is-ethereum-start-business-desc-2")}
-
- {t("page-what-is-ethereum-start-business-desc-3")}
-
-
- {t("page-what-is-ethereum-start-business-benefit-1")}
-
-
- {t("page-what-is-ethereum-start-business-benefit-2")}
-
-
- {t("page-what-is-ethereum-start-business-benefit-3")}
-
-
-
-
- {t.rich("page-what-is-ethereum-start-business-example", {
- a: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
-
-
- {t("page-what-is-ethereum-start-business-cta")}
-
-
-
-
-
-
-
- {tocItems[6].title}
-
+
-
-
{t("page-what-is-ethereum-bitcoin-intro-1")}
+
+ {t("page-what-is-ethereum-network-learn-more")}
+
+
-
- {t.rich("page-what-is-ethereum-bitcoin-intro-2", {
- strong: Strong,
- })}
-
+
+
+
+
+ {tocItems[2].title}
+
+
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-1-title")}
-
-
{t("page-what-is-ethereum-bitcoin-comparison-1-desc")}
+
+
{t("page-what-is-ethereum-ether-intro-1")}
+
+ {t.rich("page-what-is-ethereum-ether-intro-2", {
+ strong: Strong,
+ })}
+
+
+ {t.rich("page-what-is-ethereum-ether-intro-3", {
+ strong: Strong,
+ })}
+
+
+ {t.rich("page-what-is-ethereum-ether-intro-4", {
+ strong: Strong,
+ })}
+
+
+ {t.rich("page-what-is-ethereum-ether-intro-5", {
+ strong: Strong,
+ })}
+
+
{t("page-what-is-ethereum-ether-intro-6")}
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-2-title")}
-
-
{t("page-what-is-ethereum-bitcoin-comparison-2-desc")}
+
+ {t("page-what-is-ethereum-ether-learn-more")}
+
+
+
+
+
+
+
+ {tocItems[3].title}
+
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-3-title")}
-
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-3-desc-1")}
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-3-desc-2")}
-
+
+
+ {t.rich("page-what-is-ethereum-how-intro-1", {
+ strong: Strong,
+ })}
+
+
{t("page-what-is-ethereum-how-intro-2")}
+
+ {t.rich("page-what-is-ethereum-how-intro-3", {
+ strong: Strong,
+ a: (chunks) => (
+ {chunks}
+ ),
+ })}
+
+
{t("page-what-is-ethereum-how-intro-4")}
+
{t("page-what-is-ethereum-how-intro-5")}
+
+ {t("page-what-is-ethereum-how-example-1-title")}
+
+
+
+ {t("page-what-is-ethereum-how-example-1-step-1")}
+
+
+ {t("page-what-is-ethereum-how-example-1-step-2")}
+
+
+ {t("page-what-is-ethereum-how-example-1-step-3")}
+
+
+ {t("page-what-is-ethereum-how-example-1-step-4")}
+
+
+ {t("page-what-is-ethereum-how-example-1-step-5")}
+
+
+ {t("page-what-is-ethereum-how-example-1-step-6")}
+
+
+
+ {t("page-what-is-ethereum-how-example-2-title")}
+
+
+
+ {t("page-what-is-ethereum-how-example-2-step-1")}
+
+
+ {t("page-what-is-ethereum-how-example-2-step-2")}
+
+
+ {t("page-what-is-ethereum-how-example-2-step-3")}
+
+
+ {t("page-what-is-ethereum-how-example-2-step-4")}
+
+
+ {t("page-what-is-ethereum-how-example-2-step-5")}
+
+
+
{t("page-what-is-ethereum-how-outro-1")}
+
+ {t.rich("page-what-is-ethereum-how-outro-2", {
+ strong: Strong,
+ })}
+
+
+
+ {t("page-what-is-ethereum-how-learn-more-1")}
+
+
+ {t("page-what-is-ethereum-how-learn-more-2")}
+
+
+
+
+
+
+ {tocItems[4].title}
+
+
+
{t("page-what-is-ethereum-what-intro-1")}
+
+ {t.rich("page-what-is-ethereum-what-intro-2", {
+ strong: Strong,
+ insurance: (chunks) => (
+
+ {chunks}
+
+ ),
+ payment: (chunks) => (
+
+ {chunks}
+
+ ),
+ aid: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
+
{t("page-what-is-ethereum-what-intro-3")}
+
{t("page-what-is-ethereum-what-intro-4")}
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-what-consumers-title")}
+
+
+ {t("page-what-is-ethereum-what-consumers-desc-1")}
+ {t("page-what-is-ethereum-what-consumers-desc-2")}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-consumers-benefit-1",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-consumers-benefit-2",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-consumers-benefit-3",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+ {t("page-what-is-ethereum-what-consumers-benefit-4")}
+
+
+
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-what-businesses-title")}
+
+
+
+
+ {t("page-what-is-ethereum-what-businesses-benefit-1")}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-businesses-benefit-2",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+ {t("page-what-is-ethereum-what-businesses-benefit-3")}
+
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-businesses-example",
+ {
+ a: (chunks) => (
+
+ {chunks}
+
+ ),
+ }
+ )}
+
+
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-what-governments-title")}
+
+
+ {t("page-what-is-ethereum-what-governments-intro")}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-governments-benefit-1",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-governments-benefit-2",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-governments-benefit-3",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+
+ {t.rich(
+ "page-what-is-ethereum-what-governments-example-1",
+ {
+ a: (chunks) => (
+
+ {chunks}
+
+ ),
+ }
+ )}
+
+
+ {t("page-what-is-ethereum-what-governments-example-2")}
+
+
+
+
+
+
+ {/* // TODO: Re-enable when page ready */}
+ {/*
+ {t("page-what-is-ethereum-what-learn-more")}
+ */}
+
+
+
-
- {t("page-what-is-ethereum-bitcoin-comparison-4-title")}
-
+
+ {tocItems[5].title}
+
-
- {t.rich(
- "page-what-is-ethereum-bitcoin-comparison-4-desc-1",
- { strong: Strong }
- )}
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-4-desc-2")}
-
-
- {t("page-what-is-ethereum-bitcoin-comparison-4-desc-3")}
-
+
{t("page-what-is-ethereum-start-intro-1")}
+
{t("page-what-is-ethereum-start-intro-2")}
- {/* // TODO: Re-enable when page ready */}
- {/*
- {t("page-what-is-ethereum-bitcoin-learn-more")}
- */}
-
-
-
-
-
+
+
+
+ {t("page-what-is-ethereum-start-individuals-title")}
+
+
+
+
+
+ {t("page-what-is-ethereum-start-individuals-desc-1")}
+
+
-
-
- {tocItems[7].title}
+
+ {t.rich(
+ "page-what-is-ethereum-start-individuals-desc-3",
+ {
+ zerion: (chunks) => (
+ {chunks}
+ ),
+ rainbow: (chunks) => (
+ {chunks}
+ ),
+ coinbase: (chunks) => (
+
+ {chunks}
+
+ ),
+ }
+ )}
+
+
+
+
+ {t("page-what-is-ethereum-start-individuals-step-1")}
+
+
+ {t("page-what-is-ethereum-start-individuals-step-2")}
+
+
+ {t.rich(
+ "page-what-is-ethereum-start-individuals-step-3",
+ {
+ zora: (chunks) => (
+ {chunks}
+ ),
+ uniswap: (chunks) => (
+
+ {chunks}
+
+ ),
+ farcaster: (chunks) => (
+
+ {chunks}
+
+ ),
+ }
+ )}
+
+
+
+
{t("page-what-is-ethereum-start-individuals-desc-4")}
+
{t("page-what-is-ethereum-start-individuals-desc-5")}
+
+
+
+
+ {t("page-what-is-ethereum-start-individuals-cta-1")}
+
+
+ {t("page-what-is-ethereum-start-individuals-cta-2")}
+
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-start-developers-title")}
+
+
+
+
{t("page-what-is-ethereum-start-developers-desc-1")}
+
+ {t.rich("page-what-is-ethereum-start-developers-desc-2", {
+ a: (chunks) => (
+ {chunks}
+ ),
+ })}
+
+
+ {t.rich("page-what-is-ethereum-start-developers-desc-3", {
+ hardhat: (chunks) => (
+ {chunks}
+ ),
+ foundry: (chunks) => (
+ {chunks}
+ ),
+ ethers: (chunks) => (
+ {chunks}
+ ),
+ thirdweb: (chunks) => (
+ {chunks}
+ ),
+ moralis: (chunks) => (
+ {chunks}
+ ),
+ })}
+
+
{t("page-what-is-ethereum-start-developers-desc-4")}
+
+
+ {t("page-what-is-ethereum-start-developers-cta")}
+
+
+
+
+
+
+
+ {t("page-what-is-ethereum-start-business-title")}
+
+
+
+
{t("page-what-is-ethereum-start-business-desc-1")}
+
{t("page-what-is-ethereum-start-business-desc-2")}
+
+ {t("page-what-is-ethereum-start-business-desc-3")}
+
+
+ {t("page-what-is-ethereum-start-business-benefit-1")}
+
+
+ {t("page-what-is-ethereum-start-business-benefit-2")}
+
+
+ {t("page-what-is-ethereum-start-business-benefit-3")}
+
+
+
+
+ {t.rich("page-what-is-ethereum-start-business-example", {
+ a: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
+
+
+ {t("page-what-is-ethereum-start-business-cta")}
+
+
+
+
+
+
+
+ {tocItems[6].title}
-
-
-
{t("page-what-is-ethereum-when-who-intro-1")}
-
{t("page-what-is-ethereum-when-who-intro-2")}
-
{t("page-what-is-ethereum-when-who-intro-3")}
-
{t("page-what-is-ethereum-when-who-intro-4")}
+
+
+
{t("page-what-is-ethereum-bitcoin-intro-1")}
+
+
+ {t.rich("page-what-is-ethereum-bitcoin-intro-2", {
+ strong: Strong,
+ })}
+
+
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-1-title")}
+
+
{t("page-what-is-ethereum-bitcoin-comparison-1-desc")}
-
-
- {t("page-what-is-ethereum-when-who-history-title")}
+
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-2-title")}
-
-
- 2013:{" "}
- {t("page-what-is-ethereum-when-who-history-2013")}
-
-
- 2014:{" "}
- {t("page-what-is-ethereum-when-who-history-2014")}
-
-
- 2015:{" "}
- {t.rich("page-what-is-ethereum-when-who-history-2015", {
- em: Emphasis,
+ {t("page-what-is-ethereum-bitcoin-comparison-2-desc")}
+
+
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-3-title")}
+
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-3-desc-1")}
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-3-desc-2")}
+
+
+
+
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-4-title")}
+
+
+
+ {t.rich(
+ "page-what-is-ethereum-bitcoin-comparison-4-desc-1",
+ { strong: Strong }
+ )}
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-4-desc-2")}
+
+
+ {t("page-what-is-ethereum-bitcoin-comparison-4-desc-3")}
+
+
+
+
+ {/* // TODO: Re-enable when page ready */}
+ {/*
+ {t("page-what-is-ethereum-bitcoin-learn-more")}
+ */}
+
+
+
+
+
+
+
+
+ {tocItems[7].title}
+
+
+
+
{t("page-what-is-ethereum-when-who-intro-1")}
+
{t("page-what-is-ethereum-when-who-intro-2")}
+
{t("page-what-is-ethereum-when-who-intro-3")}
+
{t("page-what-is-ethereum-when-who-intro-4")}
+
+
+
+ {t("page-what-is-ethereum-when-who-history-title")}
+
+
+
+
+ 2013:
+ {" "}
+ {t("page-what-is-ethereum-when-who-history-2013")}
+
+
+
+ 2014:
+ {" "}
+ {t("page-what-is-ethereum-when-who-history-2014")}
+
+
+
+ 2015:
+ {" "}
+ {t.rich("page-what-is-ethereum-when-who-history-2015", {
+ em: Emphasis,
+ })}
+
+
+
+ 2016:
+ {" "}
+ {t("page-what-is-ethereum-when-who-history-2016")}{" "}
+
+
+
+ 2020:
+ {" "}
+ {t("page-what-is-ethereum-when-who-history-2020")}{" "}
+
+
+
+ 2021:
+ {" "}
+ {t.rich("page-what-is-ethereum-when-who-history-2021", {
+ em: Emphasis,
+ })}{" "}
+
+
+
+ 2022:
+ {" "}
+ {t.rich("page-what-is-ethereum-when-who-history-2022", {
+ em: Emphasis,
+ })}{" "}
+
+
+
+ 2025:
+ {" "}
+ {t.rich("page-what-is-ethereum-when-who-history-2025", {
+ em: Emphasis,
+ })}{" "}
+
+
+
{t("page-what-is-ethereum-when-who-governance-1")}
+
+
+
+
+ {t("page-what-is-ethereum-when-who-contributors-title")}
+
+
+
+ {t("page-what-is-ethereum-when-who-contributors-1")}
+
+
+ {t("page-what-is-ethereum-when-who-contributors-2")}
+
+
+ {" "}
+ {t("page-what-is-ethereum-when-who-contributors-3")}
+
+
+ {t("page-what-is-ethereum-when-who-contributors-4")}
+
+
+ {t.rich(
+ "page-what-is-ethereum-when-who-contributors-5",
+ {
+ strong: Strong,
+ }
+ )}
+
+
+
+ {t.rich("page-what-is-ethereum-when-who-governance-2", {
+ strong: Strong,
})}
-
-
- 2016:{" "}
- {t("page-what-is-ethereum-when-who-history-2016")}{" "}
-
-
- 2020:{" "}
- {t("page-what-is-ethereum-when-who-history-2020")}{" "}
-
-
- 2021:{" "}
- {t.rich("page-what-is-ethereum-when-who-history-2021", {
- em: Emphasis,
- })}{" "}
-
-
- 2022:{" "}
- {t.rich("page-what-is-ethereum-when-who-history-2022", {
- em: Emphasis,
- })}{" "}
-
-
- 2025:{" "}
- {t.rich("page-what-is-ethereum-when-who-history-2025", {
- em: Emphasis,
- })}{" "}
-
-
-
{t("page-what-is-ethereum-when-who-governance-1")}
+
+
+ {t.rich("page-what-is-ethereum-when-who-governance-3", {
+ eips: (chunks) => (
+
+ {chunks}
+
+ ),
+ governance: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
+
{t("page-what-is-ethereum-when-who-governance-4")}
+
+
+ {t("page-what-is-ethereum-when-who-learn-more")}
+
-
+
+
+
+
+
+ {tocItems[8].title}
+
+
-
- {t("page-what-is-ethereum-when-who-contributors-title")}
-
+
{t("page-what-is-ethereum-roadmap-intro-1")}
+
{t("page-what-is-ethereum-roadmap-intro-2")}
+
+ {t.rich("page-what-is-ethereum-roadmap-intro-3", {
+ a: (chunks) => (
+ {chunks}
+ ),
+ })}
+
+
+ {t.rich("page-what-is-ethereum-roadmap-priorities-intro", {
+ a: (chunks) => (
+
+ {chunks}
+
+ ),
+ })}
+
+
- {t("page-what-is-ethereum-when-who-contributors-1")}
-
-
- {t("page-what-is-ethereum-when-who-contributors-2")}
-
-
- {" "}
- {t("page-what-is-ethereum-when-who-contributors-3")}
+ {t("page-what-is-ethereum-roadmap-priority-1")}
- {t("page-what-is-ethereum-when-who-contributors-4")}
-
-
- {t.rich("page-what-is-ethereum-when-who-contributors-5", {
- strong: Strong,
- })}
+ {t("page-what-is-ethereum-roadmap-priority-2")}
+
+
{t("page-what-is-ethereum-roadmap-outro-1")}
- {t.rich("page-what-is-ethereum-when-who-governance-2", {
- strong: Strong,
- })}
-
-
- {t.rich("page-what-is-ethereum-when-who-governance-3", {
- eips: (chunks) => (
- {chunks}
- ),
- governance: (chunks) => (
- {chunks}
- ),
+ {t.rich("page-what-is-ethereum-roadmap-outro-2", {
+ a: (chunks) => {chunks},
})}
-
{t("page-what-is-ethereum-when-who-governance-4")}
-
- {t("page-what-is-ethereum-when-who-learn-more")}
+
+
+ {t("page-what-is-ethereum-roadmap-learn-more")}
-
-
-
-
-
- {tocItems[8].title}
-
-
-
-
{t("page-what-is-ethereum-roadmap-intro-1")}
-
{t("page-what-is-ethereum-roadmap-intro-2")}
-
- {t.rich("page-what-is-ethereum-roadmap-intro-3", {
- a: (chunks) => (
- {chunks}
- ),
- })}
-
-
- {t.rich("page-what-is-ethereum-roadmap-priorities-intro", {
- a: (chunks) => (
-
- {chunks}
-
- ),
- })}
-
+
-
-
- {t("page-what-is-ethereum-roadmap-priority-1")}
-
-
- {t("page-what-is-ethereum-roadmap-priority-2")}
-
-
-
-
{t("page-what-is-ethereum-roadmap-outro-1")}
-
- {t.rich("page-what-is-ethereum-roadmap-outro-2", {
- a: (chunks) => {chunks},
- })}
-
-
+
+
+ {t("page-what-is-ethereum-further-reading-title")}
+
+
+
+
+ {t("page-what-is-ethereum-further-reading-wallets")}
+
+
+
+
+ {t("page-what-is-ethereum-further-reading-eth")}
+
+
+
+
+ {t("page-what-is-ethereum-further-reading-web3")}
+
+
+
+
+ {t("page-what-is-ethereum-further-reading-networks")}
+
+
+
+
-
- {t("page-what-is-ethereum-roadmap-learn-more")}
-
-
-
-
-
-
- {t("page-what-is-ethereum-further-reading-title")}
-
-
-
-
- {t("page-what-is-ethereum-further-reading-wallets")}
-
-
-
-
- {t("page-what-is-ethereum-further-reading-eth")}
-
-
-
-
- {t("page-what-is-ethereum-further-reading-web3")}
-
-
-
-
- {t("page-what-is-ethereum-further-reading-networks")}
-
-
-
-
-
-
-
-
-
+
+
+
+
+ >
)
}
diff --git a/src/components/PageJsonLD.tsx b/src/components/PageJsonLD.tsx
new file mode 100644
index 00000000000..b47d5f220a5
--- /dev/null
+++ b/src/components/PageJsonLD.tsx
@@ -0,0 +1,21 @@
+interface PageJsonLDProps {
+ structuredData: Record | Record[]
+}
+
+export default function PageJsonLD({ structuredData }: PageJsonLDProps) {
+ const jsonLdArray = Array.isArray(structuredData)
+ ? structuredData
+ : [structuredData]
+
+ return (
+ <>
+ {jsonLdArray.map((data, index) => (
+
+ ))}
+ >
+ )
+}
diff --git a/src/components/Simulator/index.tsx b/src/components/Simulator/index.tsx
index 5d0a0cd15d7..1e7202ce7b1 100644
--- a/src/components/Simulator/index.tsx
+++ b/src/components/Simulator/index.tsx
@@ -1,3 +1,5 @@
+"use client"
+
import { type ReactNode, useEffect, useMemo, useState } from "react"
import { useSearchParams } from "next/navigation"
diff --git a/src/components/Simulator/screens/ConnectWeb3/index.tsx b/src/components/Simulator/screens/ConnectWeb3/index.tsx
index 4939dd26ec6..740c1ed26d6 100644
--- a/src/components/Simulator/screens/ConnectWeb3/index.tsx
+++ b/src/components/Simulator/screens/ConnectWeb3/index.tsx
@@ -1,3 +1,5 @@
+"use client"
+
import { useEffect, useMemo, useState } from "react"
import { AnimatePresence, motion } from "framer-motion"
diff --git a/src/components/Simulator/screens/CreateAccount/index.tsx b/src/components/Simulator/screens/CreateAccount/index.tsx
index a8fd08fdc16..eb4cfd7a484 100644
--- a/src/components/Simulator/screens/CreateAccount/index.tsx
+++ b/src/components/Simulator/screens/CreateAccount/index.tsx
@@ -1,3 +1,5 @@
+"use client"
+
import React, { useState } from "react"
import type { PhoneScreenProps } from "@/lib/types"
diff --git a/src/components/Simulator/screens/SendReceive/index.tsx b/src/components/Simulator/screens/SendReceive/index.tsx
index a82ab66120a..a47522b011f 100644
--- a/src/components/Simulator/screens/SendReceive/index.tsx
+++ b/src/components/Simulator/screens/SendReceive/index.tsx
@@ -1,3 +1,5 @@
+"use client"
+
import React, { useEffect, useMemo, useState } from "react"
import isChromatic from "chromatic"
diff --git a/src/data/WalletSimulatorData.tsx b/src/data/WalletSimulatorData.tsx
index 094ec84f345..e8be24148b5 100644
--- a/src/data/WalletSimulatorData.tsx
+++ b/src/data/WalletSimulatorData.tsx
@@ -1,3 +1,5 @@
+"use client"
+
import { Stack } from "@/components/ui/flex"
import Link from "@/components/ui/Link"
import { ListItem, OrderedList, UnorderedList } from "@/components/ui/list"
diff --git a/src/intl/en/page-community.json b/src/intl/en/page-community.json
index 0a44a44a5e2..50227a122f9 100644
--- a/src/intl/en/page-community.json
+++ b/src/intl/en/page-community.json
@@ -32,7 +32,7 @@
"page-community-hero-title": "Join the community",
"page-community-meetuplist-no-meetups": "We don't have any meetups matching this search. Know of one?",
"page-community-meta-title": "Community Hub",
- "page-community-meta-description": "Community homepage description",
+ "page-community-meta-description": "Community hub for the Ethereum ecosystem",
"page-community-open-source": "Creator? Builder? Get paid for your work.",
"page-community-open-source-description": "Are you building on Ethereum, or do you want to? Companies are hiring for thousands of technical and non-technical roles. Got an idea of your own? Try finding a grant to get your project off the ground.",
"page-community-open-source-image-alt": "Get paid for your work",
diff --git a/src/lib/types.ts b/src/lib/types.ts
index 104e7daf8d3..e5eb09d1df4 100644
--- a/src/lib/types.ts
+++ b/src/lib/types.ts
@@ -1013,6 +1013,7 @@ export type EventCardProps = {
export type PageWithContributorsProps = {
contributors: FileContributor[]
lastEditLocaleTimestamp: string
+ locale?: Lang
}
export type BreakpointKey = keyof typeof screens
diff --git a/src/lib/utils/url.ts b/src/lib/utils/url.ts
index 8c6cf4616b1..4452476f903 100644
--- a/src/lib/utils/url.ts
+++ b/src/lib/utils/url.ts
@@ -1,5 +1,7 @@
import { extname, join } from "path"
+import { Lang } from "@/lib/types"
+
import {
DEFAULT_LOCALE,
DISCORD_PATH,
@@ -75,3 +77,15 @@ export const slugify = (text: string): string => {
.replace(/^-|-$/g, "") // Remove leading/trailing hyphens
)
}
+
+export const normalizeUrlForJsonLd = (
+ locale: string | Lang | undefined,
+ pathWithoutLocale: string
+): string => {
+ if (!locale) {
+ return new URL(pathWithoutLocale, SITE_URL).toString()
+ }
+ const path = join(locale === DEFAULT_LOCALE ? "" : locale, pathWithoutLocale)
+ const url = new URL(path, SITE_URL)
+ return url.toString()
+}
- 6. {t("page-trillion-dollar-security-social-title")} -
-{t("page-trillion-dollar-security-section-6-intro")}
-- {t("page-trillion-dollar-security-section-6-paragraph-1")} -
-+ 6. {t("page-trillion-dollar-security-social-title")} +
+{t("page-trillion-dollar-security-section-6-intro")}
++ {t("page-trillion-dollar-security-section-6-paragraph-1")} +
+- {t("page-trillion-dollar-security-section-6-1-title")} -
-- {t("page-trillion-dollar-security-section-6-1-paragraph-1")} -
-- {t("page-trillion-dollar-security-section-6-1-paragraph-2")} -
--
- {t("page-trillion-dollar-security-section-6-1-list-1")}
-
- -
- {t("page-trillion-dollar-security-section-6-1-list-2")}
-
- -
- {t("page-trillion-dollar-security-section-6-1-list-3")}
-
-
-- {t("page-trillion-dollar-security-section-6-1-paragraph-3")} -
-+ {t("page-trillion-dollar-security-section-6-1-title")} +
++ {t( + "page-trillion-dollar-security-section-6-1-paragraph-1" + )} +
++ {t( + "page-trillion-dollar-security-section-6-1-paragraph-2" + )} +
+-
+ {t("page-trillion-dollar-security-section-6-1-list-1")}
+
+ -
+ {t("page-trillion-dollar-security-section-6-1-list-2")}
+
+ -
+ {t("page-trillion-dollar-security-section-6-1-list-3")}
+
+
++ {t( + "page-trillion-dollar-security-section-6-1-paragraph-3" + )} +
+- {t("page-trillion-dollar-security-section-6-2-title")} -
-- {t("page-trillion-dollar-security-section-6-2-paragraph-1")} -
-- {t("page-trillion-dollar-security-section-6-2-paragraph-2")} -
-+ {t("page-trillion-dollar-security-section-6-2-title")} +
++ {t( + "page-trillion-dollar-security-section-6-2-paragraph-1" + )} +
++ {t( + "page-trillion-dollar-security-section-6-2-paragraph-2" + )} +
+- {t("page-trillion-dollar-security-section-6-3-title")} -
-- {t("page-trillion-dollar-security-section-6-3-paragraph")} -
-+ {t("page-trillion-dollar-security-section-6-3-title")} +
++ {t("page-trillion-dollar-security-section-6-3-paragraph")} +
+- {t("page-trillion-dollar-security-section-6-4-title")} -
-- {t("page-trillion-dollar-security-section-6-4-paragraph-1")} -
-- {t("page-trillion-dollar-security-section-6-4-paragraph-2")} -
++ {t("page-trillion-dollar-security-section-6-4-title")} +
++ {t( + "page-trillion-dollar-security-section-6-4-paragraph-1" + )} +
++ {t( + "page-trillion-dollar-security-section-6-4-paragraph-2" + )} +
+