diff --git a/app/[locale]/10years/page-jsonld.tsx b/app/[locale]/10years/page-jsonld.tsx new file mode 100644 index 00000000000..1ec697cab94 --- /dev/null +++ b/app/[locale]/10years/page-jsonld.tsx @@ -0,0 +1,143 @@ +import { getTranslations } from "next-intl/server" + +import { FileContributor } from "@/lib/types" + +import PageJsonLD from "@/components/PageJsonLD" + +import { normalizeUrlForJsonLd } from "@/lib/utils/url" + +export default async function TenYearJsonLD({ + locale, + contributors, +}: { + locale: string + contributors: FileContributor[] +}) { + const t = await getTranslations({ + namespace: "page-10-year-anniversary", + }) + + const url = normalizeUrlForJsonLd(locale, "/10years/") + + const contributorList = contributors.map((contributor) => ({ + "@type": "Person", + name: contributor.login, + url: contributor.html_url, + })) + + const webPageJsonLd = { + "@context": "https://schema.org", + "@type": "WebPage", + "@id": url, + name: t("page-10-year-anniversary-meta-title"), + description: t("page-10-year-anniversary-meta-description"), + url: url, + inLanguage: locale, + author: [ + { + "@type": "Organization", + name: "ethereum.org", + url: "https://ethereum.org", + }, + ], + contributor: contributorList, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-10-year-anniversary-meta-title"), + item: url, + }, + ], + }, + publisher: { + "@type": "Organization", + name: "ethereum.org", + url: "https://ethereum.org", + logo: { + "@type": "ImageObject", + url: "https://ethereum.org/assets/eth-logo.png", + width: "256", + height: "417", + }, + }, + reviewedBy: { + "@type": "Organization", + name: "ethereum.org", + url: "https://ethereum.org", + logo: { + "@type": "ImageObject", + url: "https://ethereum.org/images/eth-home-icon.png", + }, + }, + mainEntity: { + "@type": "Event", + "@id": `${url}#ethereum-10-year-anniversary`, + }, + } + + const eventJsonLd = { + "@context": "https://schema.org", + "@type": "Event", + "@id": `${url}#ethereum-10-year-anniversary`, + name: t("page-10-year-anniversary-meta-title"), + description: t("page-10-year-anniversary-meta-description"), + startDate: "2024-07-30", + endDate: "2024-07-30", + eventStatus: "https://schema.org/EventCompleted", + eventAttendanceMode: "https://schema.org/OnlineEventAttendanceMode", + url: url, + organizer: { + "@type": "Organization", + name: "Ethereum Foundation", + url: "https://ethereum.org", + }, + location: { + "@type": "VirtualLocation", + url: url, + }, + image: { + "@type": "ImageObject", + url: "https://ethereum.org/assets/10-years/10-years-hero.png", + width: "1200", + height: "630", + }, + } + + const videoJsonLd = { + "@context": "https://schema.org", + "@type": "VideoObject", + name: "Ethereum: 10 Years Anniversary", + description: t("page-10-year-anniversary-meta-description"), + thumbnailUrl: "https://i.ytimg.com/vi/gjwr-7PgpTC/maxresdefault.jpg", + uploadDate: "2024-07-30", + duration: "PT5M30S", + embedUrl: "https://www.youtube.com/embed/gjwr-7PgpTC", + publisher: { + "@type": "Organization", + name: "Ethereum Foundation", + 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]/10years/page.tsx b/app/[locale]/10years/page.tsx index 45b105d83e7..c151534fee7 100644 --- a/app/[locale]/10years/page.tsx +++ b/app/[locale]/10years/page.tsx @@ -5,7 +5,7 @@ import { setRequestLocale, } from "next-intl/server" -import type { Lang } from "@/lib/types" +import type { CommitHistory, Lang } from "@/lib/types" import Emoji from "@/components/Emoji" import I18nProvider from "@/components/I18nProvider" @@ -18,6 +18,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import YouTube from "@/components/YouTube" 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" @@ -39,6 +40,7 @@ import { getInnovationCards, parseStoryDates, } from "./_components/utils" +import TenYearJsonLD from "./page-jsonld" import { routing } from "@/i18n/routing" import { fetch10YearEvents } from "@/lib/api/fetch10YearEvents" @@ -110,309 +112,319 @@ const Page = async ({ params }: { params: Promise<{ locale: Lang }> }) => { (holder) => !isAddressFiltered(holder.address) ) + const commitHistoryCache: CommitHistory = {} + const { contributors } = await getAppPageContributorInfo( + "10years", + locale as Lang, + commitHistoryCache + ) + return ( - - - -
-
-
-

- {t("page-10-year-hero-title")} -

-
+ <> + + + + +
+
+
+

+ {t("page-10-year-hero-title")} +

+
-
-

{t("page-10-year-hero-description")}

-

{t("page-10-year-hero-tagline")}

+
+

{t("page-10-year-hero-description")}

+

{t("page-10-year-hero-tagline")}

+
+
+
+
-
- -
-
-
-
-
-

- {t("page-10-year-livestream-title")} -

+
+
+
+

+ {t("page-10-year-livestream-title")} +

+
+
-
-
- -
-
- - - {Object.entries(fetched10YearEvents).map(([key, data]) => ( - - {data.label}  - ({data.events.length}) - - ))} - - {Object.entries(fetched10YearEvents).map(([key, data]) => { - const events = data.events.sort((a, b) => - a.country.localeCompare(b.country) - ) - const eventsByCountry = events.reduce( - (acc, event) => { - if (!acc[event.country]) { - acc[event.country] = [] - } - acc[event.country].push(event) - return acc - }, - {} as Record - ) - - return ( - -
- {Object.entries(eventsByCountry).map( - ([country, countryEvents]) => ( -
-

- - - - {country} -

-
- {countryEvents.map((event, index) => ( - -
-
- - {event.city} - -
-
- {event.host} -
-
- +
+ + + {Object.entries(fetched10YearEvents).map(([key, data]) => ( + + {data.label}  + ({data.events.length}) + + ))} + + {Object.entries(fetched10YearEvents).map(([key, data]) => { + const events = data.events.sort((a, b) => + a.country.localeCompare(b.country) + ) + const eventsByCountry = events.reduce( + (acc, event) => { + if (!acc[event.country]) { + acc[event.country] = [] + } + acc[event.country].push(event) + return acc + }, + {} as Record + ) + + return ( + +
+ {Object.entries(eventsByCountry).map( + ([country, countryEvents]) => ( +
+

+ + + + {country} +

+
+ {countryEvents.map((event, index) => ( + - {t("page-10-year-event-link")} - - - ))} +
+
+ + {event.city} + +
+
+ {event.host} +
+
+ + {t("page-10-year-event-link")} + + + ))} +
-
- ) - )} -
- - ) - })} - + ) + )} +
+ + ) + })} + +
-
- -
-
-
-
-
-