diff --git a/.all-contributorsrc b/.all-contributorsrc index 7501f55fccf..8fa87d8da4f 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -13943,6 +13943,24 @@ "contributions": [ "content" ] + }, + { + "login": "mikhaildobs", + "name": "Mikhail", + "avatar_url": "https://avatars.githubusercontent.com/u/4770810?v=4", + "profile": "http://linkdrop.io", + "contributions": [ + "tool" + ] + }, + { + "login": "Sshadow84", + "name": "shadow", + "avatar_url": "https://avatars.githubusercontent.com/u/96975661?v=4", + "profile": "https://github.com/Sshadow84", + "contributions": [ + "bug" + ] } ], "contributorsPerLine": 7, diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index e37e2936862..ce1f35ca6c1 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -21,8 +21,6 @@ jobs: - name: Get Netlify Deploy URL for branch id: netlify_deploy - if: | - github.ref_name == 'dev' || github.ref_name == 'staging' || github.ref_name == 'master' run: | npx ts-node -O '{ "module": "commonjs" }' src/scripts/get-netlify-branch-deploy.ts env: diff --git a/README.md b/README.md index 5c37316d5f2..5233af02a9c 100644 --- a/README.md +++ b/README.md @@ -2156,6 +2156,10 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Ivan Manchev
Ivan Manchev

🚧 Cypher Pepe
Cypher Pepe

🚧 Ankita Virani (ankita.eth)
Ankita Virani (ankita.eth)

🖋 + Mikhail
Mikhail

🔧 + + + shadow
shadow

🐛 diff --git a/app/[locale]/10years/page-jsonld.tsx b/app/[locale]/10years/page-jsonld.tsx index 7eac36b6c13..05cd1626f5d 100644 --- a/app/[locale]/10years/page-jsonld.tsx +++ b/app/[locale]/10years/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function TenYearJsonLD({ @@ -25,89 +29,57 @@ export default async function TenYearJsonLD({ url: contributor.html_url, })) - const webPageJsonLd = { + const jsonLd = { "@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: [ + "@graph": [ { - "@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": "WebPage", + "@id": url, + name: t("page-10-year-anniversary-meta-title"), + description: t("page-10-year-anniversary-meta-description"), + url: url, + inLanguage: locale, + author: [ethereumCommunityOrganization], + contributor: contributorList, + isPartOf: { + "@type": "WebSite", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-10-year-anniversary-meta-title"), - item: url, + 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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#video` }, }, - }, - 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 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-30T00:00:00Z", - 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", + { + "@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-30T00:00:00Z", + duration: "PT5M30S", + embedUrl: "https://www.youtube.com/embed/gjwr-7PgpTC", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, + ], } - return + return } diff --git a/app/[locale]/10years/page.tsx b/app/[locale]/10years/page.tsx index 85265f22f2a..7cb59e7109b 100644 --- a/app/[locale]/10years/page.tsx +++ b/app/[locale]/10years/page.tsx @@ -13,6 +13,7 @@ import { Image } from "@/components/Image" import MainArticle from "@/components/MainArticle" import Translation from "@/components/Translation" import { ButtonLink } from "@/components/ui/buttons/Button" +import InlineLink from "@/components/ui/Link" import { LinkBox, LinkOverlay } from "@/components/ui/link-box" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import YouTube from "@/components/YouTube" @@ -406,6 +407,12 @@ const Page = async ({ params }: { params: PageParams }) => { + +
+ + {t("page-10-year-terms-and-conditions")} + +
) diff --git a/app/[locale]/[...slug]/page-jsonld.tsx b/app/[locale]/[...slug]/page-jsonld.tsx index 64ca2bd856a..7988c0bfb7b 100644 --- a/app/[locale]/[...slug]/page-jsonld.tsx +++ b/app/[locale]/[...slug]/page-jsonld.tsx @@ -2,6 +2,10 @@ import { FileContributor, Frontmatter } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function SlugJsonLD({ @@ -48,87 +52,54 @@ export default async function SlugJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the slug page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: frontmatter.title, - description: frontmatter.description, - url: url, - inLanguage: locale, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", + "@type": "WebPage", + "@id": url, + name: frontmatter.title, + description: frontmatter.description, + url: url, + inLanguage: locale, + author: [ethereumCommunityOrganization], + contributor: contributorList, + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", + }, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: breadcrumbItems, + }, + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#article` }, }, - ], - contributor: contributorList, - isPartOf: { - "@type": "WebSite", - name: "ethereum.org", - url: "https://ethereum.org", - }, - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: breadcrumbItems, - }, - 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 - const articleJsonLd = { - "@context": "https://schema.org", - "@type": "Article", - headline: frontmatter.title, - description: frontmatter.description, - image: frontmatter.image - ? `https://ethereum.org${frontmatter.image}` - : undefined, - author: [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", + "@type": "Article", + "@id": `${url}#article`, + headline: frontmatter.title, + description: frontmatter.description, + image: frontmatter.image + ? `https://ethereum.org${frontmatter.image}` + : undefined, + author: [ethereumCommunityOrganization], + contributor: contributorList, + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + dateModified: frontmatter.published, + mainEntityOfPage: url, + about: { + "@type": "Thing", + name: frontmatter.title, + description: frontmatter.description, + }, }, ], - 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", - }, - }, - dateModified: frontmatter.published, - mainEntityOfPage: url, - about: { - "@type": "Thing", - name: frontmatter.title, - description: frontmatter.description, - }, } - return + return } diff --git a/app/[locale]/apps/[application]/page-jsonld.tsx b/app/[locale]/apps/[application]/page-jsonld.tsx index c34fcb207f0..11b065c8824 100644 --- a/app/[locale]/apps/[application]/page-jsonld.tsx +++ b/app/[locale]/apps/[application]/page-jsonld.tsx @@ -2,6 +2,10 @@ import { AppData, FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd, slugify } from "@/lib/utils/url" export default async function AppsAppJsonLD({ @@ -21,90 +25,75 @@ export default async function AppsAppJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the individual app page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: `Ethereum Apps - ${app.name}`, - description: app.description, - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: `Ethereum Apps - ${app.name}`, + description: app.description, + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: "Apps", - item: normalizeUrlForJsonLd(locale, "/apps/"), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Apps", + item: normalizeUrlForJsonLd(locale, "/apps/"), + }, + { + "@type": "ListItem", + position: 3, + name: app.name, + item: url, + }, + ], }, - { - "@type": "ListItem", - position: 3, - name: app.name, - 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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#applications` }, }, - }, - } - - const softwareApplicationJsonLd = { - "@context": "https://schema.org", - "@type": "SoftwareApplication", - name: app.name, - description: app.description, - url: app.url, - image: app.image, - applicationCategory: app.category, - applicationSubCategory: app.subCategory.join(", "), - operatingSystem: "Web Browser", - author: [ { - "@type": "Organization", - name: app.parentCompany, + "@type": "SoftwareApplication", + "@id": `${url}#applications`, + name: app.name, + description: app.description, + url: app.url, + image: app.image, + applicationCategory: app.category, + applicationSubCategory: app.subCategory.join(", "), + operatingSystem: "Web Browser", + author: [ + { + "@type": "Organization", + name: app.parentCompany, + }, + ], + datePublished: app.dateOfLaunch, + dateModified: app.lastUpdated, + inLanguage: app.languages, + screenshot: app.screenshots.slice(0, 5), + sameAs: [app.twitter, app.github, app.discord].filter(Boolean), }, ], - datePublished: app.dateOfLaunch, - dateModified: app.lastUpdated, - inLanguage: app.languages, - screenshot: app.screenshots.slice(0, 5), - sameAs: [app.twitter, app.github, app.discord].filter(Boolean), } - return ( - - ) + return } diff --git a/app/[locale]/apps/categories/[catetgoryName]/page-jsonld.tsx b/app/[locale]/apps/categories/[catetgoryName]/page-jsonld.tsx index 9164f052b1d..bca0929918b 100644 --- a/app/[locale]/apps/categories/[catetgoryName]/page-jsonld.tsx +++ b/app/[locale]/apps/categories/[catetgoryName]/page-jsonld.tsx @@ -4,6 +4,10 @@ import { AppCategoryData, AppData, FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function AppsCategoryJsonLD({ @@ -31,81 +35,68 @@ export default async function AppsCategoryJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the apps category page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t(category.metaTitle), - description: t(category.metaDescription), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t(category.metaTitle), + description: t(category.metaDescription), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: "Apps", - item: normalizeUrlForJsonLd(locale, "/apps/"), - }, - { - "@type": "ListItem", - position: 3, - name: t(category.name), - item: url, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Apps", + item: normalizeUrlForJsonLd(locale, "/apps/"), + }, + { + "@type": "ListItem", + position: 3, + name: t(category.name), + item: url, + }, + ], }, - ], - }, - publisher: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#categories` }, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", + { + "@type": "ItemList", + "@id": `${url}#categories`, + name: t(category.name), + description: t(category.description), + url: url, + numberOfItems: categoryApps.length, + itemListElement: categoryApps.slice(0, 10).map((app, index) => ({ + "@type": "ListItem", + position: index + 1, + name: app.name, + description: app.description, + url: app.url, + })), }, - }, - } - - const categoryAppsJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t(category.name), - description: t(category.description), - url: url, - numberOfItems: categoryApps.length, - itemListElement: categoryApps.slice(0, 10).map((app, index) => ({ - "@type": "ListItem", - position: index + 1, - name: app.name, - description: app.description, - url: app.url, - })), + ], } - return + return } diff --git a/app/[locale]/apps/page-jsonld.tsx b/app/[locale]/apps/page-jsonld.tsx index ad7ab9d949e..1f093efab63 100644 --- a/app/[locale]/apps/page-jsonld.tsx +++ b/app/[locale]/apps/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" import { appsCategories } from "@/data/apps/categories" @@ -25,75 +29,67 @@ export default async function AppsJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the apps page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-apps-meta-title"), - description: t("page-apps-meta-description"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-apps-meta-title"), + description: t("page-apps-meta-description"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-apps-meta-title"), - item: url, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-apps-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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#apps` }, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", + { + "@type": "ItemList", + "@id": `${url}#apps`, + name: t("page-apps-categories-title"), + description: t("page-apps-meta-description"), + url: url, + numberOfItems: Object.keys(appsCategories).length, + itemListElement: Object.values(appsCategories).map( + (category, index) => ({ + "@type": "ListItem", + position: index + 1, + name: t(category.name), + description: t(category.description), + url: normalizeUrlForJsonLd( + locale, + `/apps/categories/${category.slug}` + ), + }) + ), }, - }, - } - - const appCategoriesJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-apps-categories-title"), - description: t("page-apps-meta-description"), - url: url, - numberOfItems: Object.keys(appsCategories).length, - itemListElement: Object.values(appsCategories).map((category, index) => ({ - "@type": "ListItem", - position: index + 1, - name: t(category.name), - description: t(category.description), - url: normalizeUrlForJsonLd(locale, `/apps/categories/${category.slug}`), - })), + ], } - return + return } diff --git a/app/[locale]/assets/page-jsonld.tsx b/app/[locale]/assets/page-jsonld.tsx index ef376770bb3..228af391037 100644 --- a/app/[locale]/assets/page-jsonld.tsx +++ b/app/[locale]/assets/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function AssetsJsonLD({ @@ -23,106 +27,81 @@ export default async function AssetsJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the assets page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-assets-meta-title"), - description: t("page-assets-meta-desc"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-assets-meta-title"), + description: t("page-assets-meta-desc"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-assets-meta-title"), - item: normalizeUrlForJsonLd(locale, "/assets/"), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-assets-meta-title"), + item: normalizeUrlForJsonLd(locale, "/assets/"), + }, + ], }, - ], - }, - 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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#assets` }, }, - }, - } - - const creativeWorkJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-assets-h1"), - description: t("page-assets-meta-desc"), - url: url, - numberOfItems: 3, - itemListElement: [ { - "@type": "ListItem", - position: 1, - name: t("page-assets-illustrations"), - description: - "Artistic works by Liam Cobb, Viktor Hachmang, Patrick Atkins, and others", - url: normalizeUrlForJsonLd(locale, "/assets/#illustrations"), - }, - { - "@type": "ListItem", - position: 2, - name: t("page-assets-historical-artwork"), - description: "Historical Ethereum artwork and graphics", - url: normalizeUrlForJsonLd(locale, "/assets/#historical"), - }, - { - "@type": "ListItem", - position: 3, - name: t("page-assets-ethereum-brand-assets"), - description: "Official Ethereum brand assets, logos, and graphics", - url: normalizeUrlForJsonLd(locale, "/assets/#brand"), + "@type": "ItemList", + "@id": `${url}#assets`, + name: t("page-assets-h1"), + description: t("page-assets-meta-desc"), + url: url, + numberOfItems: 3, + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: t("page-assets-illustrations"), + description: + "Artistic works by Liam Cobb, Viktor Hachmang, Patrick Atkins, and others", + url: normalizeUrlForJsonLd(locale, "/assets/#illustrations"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-assets-historical-artwork"), + description: "Historical Ethereum artwork and graphics", + url: normalizeUrlForJsonLd(locale, "/assets/#historical"), + }, + { + "@type": "ListItem", + position: 3, + name: t("page-assets-ethereum-brand-assets"), + description: "Official Ethereum brand assets, logos, and graphics", + url: normalizeUrlForJsonLd(locale, "/assets/#brand"), + }, + ], + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, ], - 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 + return } diff --git a/app/[locale]/bug-bounty/page-jsonld.tsx b/app/[locale]/bug-bounty/page-jsonld.tsx index 74c597e4b77..292a7a3fbe8 100644 --- a/app/[locale]/bug-bounty/page-jsonld.tsx +++ b/app/[locale]/bug-bounty/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function BugBountyJsonLD({ @@ -23,59 +27,46 @@ export default async function BugBountyJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the bug bounty page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-upgrades-bug-bounty-meta-title"), - description: t("page-upgrades-bug-bounty-meta-description"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-upgrades-bug-bounty-meta-title"), + description: t("page-upgrades-bug-bounty-meta-description"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-upgrades-bug-bounty-meta-title"), - item: normalizeUrlForJsonLd(locale, "/bug-bounty/"), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-upgrades-bug-bounty-meta-title"), + item: normalizeUrlForJsonLd(locale, "/bug-bounty/"), + }, + ], }, - ], - }, - publisher: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", - }, - }, + ], } - return + return } diff --git a/app/[locale]/collectibles/page-jsonld.tsx b/app/[locale]/collectibles/page-jsonld.tsx index 30231bb5b09..3e06c6662d5 100644 --- a/app/[locale]/collectibles/page-jsonld.tsx +++ b/app/[locale]/collectibles/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" import { COLLECTIBLES_BASE_URL } from "./constants" @@ -30,111 +34,82 @@ export default async function CollectiblesJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the collectibles page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-collectibles-hero-header"), - description: t("page-collectibles-hero-description"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-collectibles-hero-header"), + description: t("page-collectibles-hero-description"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-collectibles-hero-header"), - item: url, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-collectibles-hero-header"), + 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", - }, - }, - } - - const collectiblesCollectionJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-collectibles-hero-header"), - description: t("page-collectibles-hero-description"), - url: url, - numberOfItems: stats.collectiblesCount || badges.length, - itemListElement: badges.slice(0, 10).map((badge, index) => ({ - "@type": "ListItem", - position: index + 1, - name: badge.name || `Badge ${index + 1}`, - description: badge.description || "Ethereum community badge", - url: badge.link || `${COLLECTIBLES_BASE_URL}/badge/${badge.id}`, - image: badge.image, - })), - 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", - }, - }, - additionalProperty: [ - { - "@type": "PropertyValue", - name: "Total Collectors", - value: stats.uniqueAddressesCount || 0, + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#collectibles` }, }, { - "@type": "PropertyValue", - name: "Total Minted", - value: stats.collectorsCount || 0, - }, - { - "@type": "PropertyValue", - name: "Unique Badges", - value: stats.collectiblesCount || badges.length, + "@type": "ItemList", + "@id": `${url}#collectibles`, + name: t("page-collectibles-hero-header"), + description: t("page-collectibles-hero-description"), + url: url, + numberOfItems: stats.collectiblesCount || badges.length, + itemListElement: badges.slice(0, 10).map((badge, index) => ({ + "@type": "ListItem", + position: index + 1, + name: badge.name || `Badge ${index + 1}`, + description: badge.description || "Ethereum community badge", + url: badge.link || `${COLLECTIBLES_BASE_URL}/badge/${badge.id}`, + image: badge.image, + })), + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + additionalProperty: [ + { + "@type": "PropertyValue", + name: "Total Collectors", + value: stats.uniqueAddressesCount || 0, + }, + { + "@type": "PropertyValue", + name: "Total Minted", + value: stats.collectorsCount || 0, + }, + { + "@type": "PropertyValue", + name: "Unique Badges", + value: stats.collectiblesCount || badges.length, + }, + ], }, ], } - return ( - - ) + return } diff --git a/app/[locale]/community/page-jsonld.tsx b/app/[locale]/community/page-jsonld.tsx index ce14986275f..87bb4aa98d8 100644 --- a/app/[locale]/community/page-jsonld.tsx +++ b/app/[locale]/community/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function CommunityJsonLD({ @@ -23,114 +27,87 @@ export default async function CommunityJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the community page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-community-meta-title"), - description: t("page-community-meta-description"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-community-meta-title"), + description: t("page-community-meta-description"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-community-meta-title"), - item: url, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-community-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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#resources` }, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", - }, - }, - } - - const communityResourcesJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-community-meta-title"), - description: t("page-community-meta-description"), - url: url, - numberOfItems: 4, - itemListElement: [ { - "@type": "ListItem", - position: 1, - name: t("page-community-card-1-title"), - description: t("page-community-card-1-description"), - url: normalizeUrlForJsonLd(locale, "/community/online/"), - }, - { - "@type": "ListItem", - position: 2, - name: t("page-community-card-2-title"), - description: t("page-community-card-2-description"), - url: normalizeUrlForJsonLd(locale, "/community/events/"), - }, - { - "@type": "ListItem", - position: 3, - name: t("page-community-card-3-title"), - description: t("page-community-card-3-description"), - url: normalizeUrlForJsonLd(locale, "/community/get-involved/"), - }, - { - "@type": "ListItem", - position: 4, - name: t("page-community-card-4-title"), - description: t("page-community-card-4-description"), - url: normalizeUrlForJsonLd(locale, "/community/grants/"), + "@type": "ItemList", + "@id": `${url}#resources`, + name: t("page-community-meta-title"), + description: t("page-community-meta-description"), + url: url, + numberOfItems: 4, + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: t("page-community-card-1-title"), + description: t("page-community-card-1-description"), + url: normalizeUrlForJsonLd(locale, "/community/online/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-community-card-2-title"), + description: t("page-community-card-2-description"), + url: normalizeUrlForJsonLd(locale, "/community/events/"), + }, + { + "@type": "ListItem", + position: 3, + name: t("page-community-card-3-title"), + description: t("page-community-card-3-description"), + url: normalizeUrlForJsonLd(locale, "/community/get-involved/"), + }, + { + "@type": "ListItem", + position: 4, + name: t("page-community-card-4-title"), + description: t("page-community-card-4-description"), + url: normalizeUrlForJsonLd(locale, "/community/grants/"), + }, + ], + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, ], - 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 ( - - ) + return } diff --git a/app/[locale]/contributing/translation-program/acknowledgements/page-jsonld.tsx b/app/[locale]/contributing/translation-program/acknowledgements/page-jsonld.tsx index 55b9cb048b4..927d8272a6f 100644 --- a/app/[locale]/contributing/translation-program/acknowledgements/page-jsonld.tsx +++ b/app/[locale]/contributing/translation-program/acknowledgements/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function AcknowledgementsJsonLD({ @@ -28,80 +32,67 @@ export default async function AcknowledgementsJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the translation acknowledgements page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t( - "page-contributing-translation-program-acknowledgements-meta-title" - ), - description: t( - "page-contributing-translation-program-acknowledgements-meta-description" - ), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@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: "Contributing", - item: normalizeUrlForJsonLd(locale, "/contributing/"), + "@type": "WebPage", + "@id": url, + name: t( + "page-contributing-translation-program-acknowledgements-meta-title" + ), + description: t( + "page-contributing-translation-program-acknowledgements-meta-description" + ), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 3, - name: "Translation Program", - item: normalizeUrlForJsonLd( - locale, - "/contributing/translation-program/" - ), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Contributing", + item: normalizeUrlForJsonLd(locale, "/contributing/"), + }, + { + "@type": "ListItem", + position: 3, + name: "Translation Program", + item: normalizeUrlForJsonLd( + locale, + "/contributing/translation-program/" + ), + }, + { + "@type": "ListItem", + position: 4, + name: t( + "page-contributing-translation-program-acknowledgements-meta-title" + ), + item: url, + }, + ], }, - { - "@type": "ListItem", - position: 4, - name: t( - "page-contributing-translation-program-acknowledgements-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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, + ], } - return + return } diff --git a/app/[locale]/contributing/translation-program/contributors/page-jsonld.tsx b/app/[locale]/contributing/translation-program/contributors/page-jsonld.tsx index f6567850a42..ea2726760af 100644 --- a/app/[locale]/contributing/translation-program/contributors/page-jsonld.tsx +++ b/app/[locale]/contributing/translation-program/contributors/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function ContributorsJsonLD({ @@ -28,78 +32,67 @@ export default async function ContributorsJsonLD({ `/contributing/translation-program/contributors/` ) - // JSON-LD structured data for the translation contributors page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-contributing-translation-program-contributors-meta-title"), - description: t( - "page-contributing-translation-program-contributors-meta-description" - ), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@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: "Contributing", - item: normalizeUrlForJsonLd(locale, "/contributing/"), + "@type": "WebPage", + "@id": url, + name: t( + "page-contributing-translation-program-contributors-meta-title" + ), + description: t( + "page-contributing-translation-program-contributors-meta-description" + ), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 3, - name: "Translation Program", - item: normalizeUrlForJsonLd( - locale, - "/contributing/translation-program/" - ), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Contributing", + item: normalizeUrlForJsonLd(locale, "/contributing/"), + }, + { + "@type": "ListItem", + position: 3, + name: "Translation Program", + item: normalizeUrlForJsonLd( + locale, + "/contributing/translation-program/" + ), + }, + { + "@type": "ListItem", + position: 4, + name: t( + "page-contributing-translation-program-contributors-meta-title" + ), + item: url, + }, + ], }, - { - "@type": "ListItem", - position: 4, - name: t( - "page-contributing-translation-program-contributors-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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, + ], } - return + return } diff --git a/app/[locale]/contributing/translation-program/translatathon/leaderboard/page-jsonld.tsx b/app/[locale]/contributing/translation-program/translatathon/leaderboard/page-jsonld.tsx index e3a9eb26d44..bfda73495aa 100644 --- a/app/[locale]/contributing/translation-program/translatathon/leaderboard/page-jsonld.tsx +++ b/app/[locale]/contributing/translation-program/translatathon/leaderboard/page-jsonld.tsx @@ -2,6 +2,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function TranslatathonLeaderboardJsonLD({ @@ -22,84 +26,71 @@ export default async function TranslatathonLeaderboardJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the translatathon leaderboard page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: "2025 Ethereum.org Translatathon Leaderboard", - description: - "Leaderboard for the 2025 Ethereum.org Translatathon showing translation progress and participant rankings", - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@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: "Contributing", - item: normalizeUrlForJsonLd(locale, "/contributing/"), - }, - { - "@type": "ListItem", - position: 3, - name: "Translation Program", - item: normalizeUrlForJsonLd( - locale, - "/contributing/translation-program/" - ), + "@type": "WebPage", + "@id": url, + name: "2025 Ethereum.org Translatathon Leaderboard", + description: + "Leaderboard for the 2025 Ethereum.org Translatathon showing translation progress and participant rankings", + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 4, - name: "Translatathon", - item: normalizeUrlForJsonLd( - locale, - "/contributing/translation-program/translatathon/" - ), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Contributing", + item: normalizeUrlForJsonLd(locale, "/contributing/"), + }, + { + "@type": "ListItem", + position: 3, + name: "Translation Program", + item: normalizeUrlForJsonLd( + locale, + "/contributing/translation-program/" + ), + }, + { + "@type": "ListItem", + position: 4, + name: "Translatathon", + item: normalizeUrlForJsonLd( + locale, + "/contributing/translation-program/translatathon/" + ), + }, + { + "@type": "ListItem", + position: 5, + name: "Leaderboard", + item: url, + }, + ], }, - { - "@type": "ListItem", - position: 5, - name: "Leaderboard", - 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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, + ], } - return + return } diff --git a/app/[locale]/developers/learning-tools/page-jsonld.tsx b/app/[locale]/developers/learning-tools/page-jsonld.tsx index 41a72fa6e1c..2a345f62c05 100644 --- a/app/[locale]/developers/learning-tools/page-jsonld.tsx +++ b/app/[locale]/developers/learning-tools/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function LearningToolsJsonLD({ @@ -25,65 +29,52 @@ export default async function LearningToolsJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the developers learning tools page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-learning-tools-meta-title"), - description: t("page-learning-tools-meta-desc"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@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: "Developers", - item: normalizeUrlForJsonLd(locale, "/developers/"), + "@type": "WebPage", + "@id": url, + name: t("page-learning-tools-meta-title"), + description: t("page-learning-tools-meta-desc"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 3, - name: t("page-learning-tools-meta-title"), - item: url, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Developers", + item: normalizeUrlForJsonLd(locale, "/developers/"), + }, + { + "@type": "ListItem", + position: 3, + name: t("page-learning-tools-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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", - }, - }, + ], } - return + return } diff --git a/app/[locale]/developers/local-environment/page-jsonld.tsx b/app/[locale]/developers/local-environment/page-jsonld.tsx index b540579a324..3728c0a78d7 100644 --- a/app/[locale]/developers/local-environment/page-jsonld.tsx +++ b/app/[locale]/developers/local-environment/page-jsonld.tsx @@ -5,6 +5,10 @@ import { Framework } from "@/lib/interfaces" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function LocalEnvironmentJsonLD({ @@ -28,108 +32,81 @@ export default async function LocalEnvironmentJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the developers local environment page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-local-environment-setup-meta-title"), - description: t("page-local-environment-setup-meta-desc"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@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: "Developers", - item: normalizeUrlForJsonLd(locale, "/developers/"), + "@type": "WebPage", + "@id": url, + name: t("page-local-environment-setup-meta-title"), + description: t("page-local-environment-setup-meta-desc"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 3, - name: t("page-local-environment-setup-meta-title"), - item: url, + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Developers", + item: normalizeUrlForJsonLd(locale, "/developers/"), + }, + { + "@type": "ListItem", + position: 3, + name: t("page-local-environment-setup-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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#local-environment` }, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", - }, - }, - } - - const developmentFrameworksJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: "Ethereum Development Frameworks", - description: - "Tools and frameworks for setting up local Ethereum development environments", - url: url, - numberOfItems: frameworksListData.length, - itemListElement: frameworksListData.map((framework, index) => ({ - "@type": "SoftwareApplication", - position: index + 1, - name: framework.name, - description: framework.description, - url: framework.url, - applicationCategory: "DeveloperApplication", - operatingSystem: ["Windows", "macOS", "Linux"], - author: [ - { - "@type": "Organization", - name: framework.githubUrl || "Community", - }, - ], - downloadUrl: framework.url, - sameAs: framework.githubUrl, - })), - 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", + { + "@type": "ItemList", + "@id": `${url}#local-environment`, + name: "Ethereum Development Frameworks", + description: + "Tools and frameworks for setting up local Ethereum development environments", + url: url, + numberOfItems: frameworksListData.length, + itemListElement: frameworksListData.map((framework, index) => ({ + "@type": "SoftwareApplication", + position: index + 1, + name: framework.name, + description: framework.description, + url: framework.url, + applicationCategory: "DeveloperApplication", + operatingSystem: ["Windows", "macOS", "Linux"], + author: [ + { + "@type": "Organization", + name: framework.githubUrl || "Community", + }, + ], + downloadUrl: framework.url, + sameAs: framework.githubUrl, + })), + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, + ], } - return ( - - ) + return } diff --git a/app/[locale]/developers/page-jsonld.tsx b/app/[locale]/developers/page-jsonld.tsx index ae9d15b45cc..5f4cb2b3928 100644 --- a/app/[locale]/developers/page-jsonld.tsx +++ b/app/[locale]/developers/page-jsonld.tsx @@ -4,6 +4,10 @@ import { CommunityConference, FileContributor } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" import { DevelopersPath, VideoCourse } from "./types" @@ -31,108 +35,81 @@ export default async function DevelopersPageJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the developers page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-developer-meta-title"), - description: t("page-developers-meta-desc"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-developer-meta-title"), + description: t("page-developers-meta-desc"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: t("page-developer-meta-title"), - item: normalizeUrlForJsonLd(locale, "/developers/"), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: t("page-developer-meta-title"), + item: normalizeUrlForJsonLd(locale, "/developers/"), + }, + ], }, - ], - }, - publisher: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#developers` }, }, - }, - reviewedBy: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - logo: { - "@type": "ImageObject", - url: "https://ethereum.org/images/eth-home-icon.png", + { + "@type": "ItemList", + "@id": `${url}#developers`, + name: t("page-developer-meta-title"), + description: + "Comprehensive resources for building on Ethereum including tutorials, tools, documentation, and courses", + url: url, + numberOfItems: paths.length + courses.length + hackathons.length, + itemListElement: [ + ...paths.map((path, index) => ({ + "@type": "ListItem", + position: index + 1, + name: path.title, + description: path.description, + url: path.href, + })), + ...courses.slice(0, 5).map((course, index) => ({ + "@type": "ListItem", + position: paths.length + index + 1, + name: course.title, + description: course.description, + url: course.href, + })), + ...hackathons.map((hackathon, index) => ({ + "@type": "ListItem", + position: paths.length + courses.length + index + 1, + name: hackathon.title, + description: hackathon.description, + url: hackathon.href, + })), + ], + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, - } - - const learningResourcesJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-developer-meta-title"), - description: - "Comprehensive resources for building on Ethereum including tutorials, tools, documentation, and courses", - url: url, - numberOfItems: paths.length + courses.length + hackathons.length, - itemListElement: [ - ...paths.map((path, index) => ({ - "@type": "ListItem", - position: index + 1, - name: path.title, - description: path.description, - url: path.href, - })), - ...courses.slice(0, 5).map((course, index) => ({ - "@type": "ListItem", - position: paths.length + index + 1, - name: course.title, - description: course.description, - url: course.href, - })), - ...hackathons.map((hackathon, index) => ({ - "@type": "ListItem", - position: paths.length + courses.length + index + 1, - name: hackathon.title, - description: hackathon.description, - url: hackathon.href, - })), ], - 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 ( - - ) + return } diff --git a/app/[locale]/developers/tutorials/page-jsonld.tsx b/app/[locale]/developers/tutorials/page-jsonld.tsx index 29a842dddc7..5cde1c24c35 100644 --- a/app/[locale]/developers/tutorials/page-jsonld.tsx +++ b/app/[locale]/developers/tutorials/page-jsonld.tsx @@ -4,6 +4,10 @@ import { FileContributor, ITutorial } from "@/lib/types" import PageJsonLD from "@/components/PageJsonLD" +import { + ethereumCommunityOrganization, + ethereumFoundationOrganization, +} from "@/lib/utils/jsonld" import { normalizeUrlForJsonLd } from "@/lib/utils/url" export default async function TutorialsPageJsonLD({ @@ -25,148 +29,102 @@ export default async function TutorialsPageJsonLD({ url: contributor.html_url, })) - // JSON-LD structured data for the developers tutorials page - const webPageJsonLd = { + const jsonLd = { "@context": "https://schema.org", - "@type": "WebPage", - "@id": url, - name: t("page-tutorials-meta-title"), - description: t("page-tutorials-meta-description"), - url: url, - inLanguage: locale, - contributor: contributorList, - author: [ + "@graph": [ { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", - }, - ], - breadcrumb: { - "@type": "BreadcrumbList", - itemListElement: [ - { - "@type": "ListItem", - position: 1, - name: "Home", - item: normalizeUrlForJsonLd(locale, "/"), + "@type": "WebPage", + "@id": url, + name: t("page-tutorials-meta-title"), + description: t("page-tutorials-meta-description"), + url: url, + inLanguage: locale, + contributor: contributorList, + author: [ethereumCommunityOrganization], + isPartOf: { + "@type": "WebSite", + "@id": "https://ethereum.org/#website", + name: "ethereum.org", + url: "https://ethereum.org", }, - { - "@type": "ListItem", - position: 2, - name: "Developers", - item: normalizeUrlForJsonLd(locale, "/developers/"), + breadcrumb: { + "@type": "BreadcrumbList", + itemListElement: [ + { + "@type": "ListItem", + position: 1, + name: "Home", + item: normalizeUrlForJsonLd(locale, "/"), + }, + { + "@type": "ListItem", + position: 2, + name: "Developers", + item: normalizeUrlForJsonLd(locale, "/developers/"), + }, + { + "@type": "ListItem", + position: 3, + name: t("page-tutorial-title"), + item: url, + }, + ], }, - { - "@type": "ListItem", - position: 3, - name: t("page-tutorial-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", - }, - }, - } - - const tutorialCollectionJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-tutorial-title"), - description: t("page-tutorials-meta-description"), - url: url, - numberOfItems: internalTutorials.length, - itemListElement: internalTutorials.slice(0, 10).map((tutorial, index) => ({ - "@type": "ListItem", - position: index + 1, - name: tutorial.title, - description: tutorial.description, - url: tutorial.href, - })), - 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", + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, + mainEntity: { "@id": `${url}#tutorials` }, }, - }, - } - - const courseListJsonLd = { - "@context": "https://schema.org", - "@type": "ItemList", - name: t("page-tutorial-title"), - description: t("page-tutorials-meta-description"), - url: url, - numberOfItems: internalTutorials.length, - itemListElement: internalTutorials.slice(0, 10).map((tutorial, index) => ({ - "@type": "Course", - name: tutorial.title, - description: tutorial.description, - url: tutorial.href, - provider: { - "@type": "Organization", - name: "ethereum.org", - url: "https://ethereum.org", + { + "@type": "ItemList", + "@id": `${url}#tutorials`, + name: t("page-tutorial-title"), + description: t("page-tutorials-meta-description"), + url: url, + numberOfItems: internalTutorials.length, + itemListElement: internalTutorials + .slice(0, 10) + .map((tutorial, index) => ({ + "@type": "ListItem", + position: index + 1, + name: tutorial.title, + description: tutorial.description, + url: tutorial.href, + })), + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - courseMode: "online", - educationalLevel: "beginner-intermediate", - inLanguage: locale, - isAccessibleForFree: true, - about: [ - "Ethereum Development", - "Smart Contracts", - "Blockchain Programming", - "Web3", - ], - position: index + 1, - })), - 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", + { + "@type": "ItemList", + "@id": `${url}#tutorials`, + name: t("page-tutorial-title"), + description: t("page-tutorials-meta-description"), + url: url, + numberOfItems: internalTutorials.length, + itemListElement: internalTutorials + .slice(0, 10) + .map((tutorial, index) => ({ + "@type": "Course", + name: tutorial.title, + description: tutorial.description, + url: tutorial.href, + provider: ethereumFoundationOrganization, + courseMode: "online", + educationalLevel: "beginner-intermediate", + inLanguage: locale, + isAccessibleForFree: true, + about: [ + "Ethereum Development", + "Smart Contracts", + "Blockchain Programming", + "Web3", + ], + position: index + 1, + })), + publisher: ethereumFoundationOrganization, + reviewedBy: ethereumFoundationOrganization, }, - }, + ], } - return ( - - ) + return } diff --git a/app/[locale]/enterprise/_components/CaseCard.tsx b/app/[locale]/enterprise/_components/CaseCard.tsx deleted file mode 100644 index 1d2336f985e..00000000000 --- a/app/[locale]/enterprise/_components/CaseCard.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Card } from "@/components/ui/card" - -import { cn } from "@/lib/utils/cn" - -import type { Case } from "../types" - -type CaseCardProps = { - caseStudy: Case - className?: string -} - -const CaseCard = ({ - caseStudy: { name, content }, - className, -}: CaseCardProps) => ( - -

{name}

-

{content}

-
-) - -export default CaseCard diff --git a/app/[locale]/enterprise/_components/CasesColumn.tsx b/app/[locale]/enterprise/_components/CasesColumn.tsx deleted file mode 100644 index 2aa1c1a51c1..00000000000 --- a/app/[locale]/enterprise/_components/CasesColumn.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { cn } from "@/lib/utils/cn" - -import type { Case } from "../types" - -import CaseCard from "./CaseCard" - -const CasesColumn = ({ - cases, - className, -}: { - cases: Case[] - className?: string -}) => ( -
- {cases.map((caseStudy, index) => ( - - ))} -
-) - -export default CasesColumn diff --git a/app/[locale]/enterprise/_components/CasesSwiper.tsx b/app/[locale]/enterprise/_components/CasesSwiper.tsx deleted file mode 100644 index 5100e3cf630..00000000000 --- a/app/[locale]/enterprise/_components/CasesSwiper.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client" - -import { Swiper, SwiperSlide } from "@/components/ui/swiper" - -import type { Case } from "../types" - -import CaseCard from "./CaseCard" - -import { useBreakpointValue } from "@/hooks/useBreakpointValue" - -const CasesSwiper = ({ cases }: { cases: Case[] }) => { - const slidesPerView = useBreakpointValue({ - base: 1.2, - sm: 2.2, - }) - - return ( - - {cases.map((caseStudy) => ( - - - - ))} - - ) -} - -export default CasesSwiper diff --git a/app/[locale]/enterprise/_components/ContactForm/index.tsx b/app/[locale]/enterprise/_components/ContactForm/index.tsx deleted file mode 100644 index 37fb3932595..00000000000 --- a/app/[locale]/enterprise/_components/ContactForm/index.tsx +++ /dev/null @@ -1,295 +0,0 @@ -"use client" - -import React, { useState } from "react" -import { HeartHandshake, TriangleAlert } from "lucide-react" - -import { Button } from "@/components/ui/buttons/Button" -import Input from "@/components/ui/input" -import { Spinner } from "@/components/ui/spinner" -import { Textarea } from "@/components/ui/textarea" - -import { cn } from "@/lib/utils/cn" -import { sanitizeInput } from "@/lib/utils/sanitize" - -import { MAX_EMAIL_LENGTH, MAX_MESSAGE_LENGTH } from "../../constants" - -type EnterpriseContactFormProps = { - strings: { - error: { - domain: React.ReactNode // Link injected - emailInvalid: string - emailTooLong: string - general: React.ReactNode // Link injected - messageTooLong: string - required: string - } - placeholder: { - input: string - textarea: string - } - button: { - label: string - loading: string - } - success: { - heading: string - message: string - } - } -} - -type FormState = { - email: string - message: string -} - -type FormErrors = { - email?: React.ReactNode - message?: React.ReactNode - general?: React.ReactNode -} - -type SubmissionState = "idle" | "submitting" | "success" | "error" - -// Consumer email domains to block -const CONSUMER_DOMAINS = [ - "gmail.com", - "yahoo.com", - "hotmail.com", - "outlook.com", - "icloud.com", - "protonmail.com", - "proton.me", - "pm.me", - "aol.com", - "mail.com", - "yandex.com", - "tutanota.com", - "fastmail.com", - "zoho.com", - "gmx.com", - "live.com", - "msn.com", - "me.com", - "mac.com", - "rocketmail.com", - "yahoo.co.uk", - "googlemail.com", - "mailinator.com", - "10minutemail.com", - "guerrillamail.com", -] - -const EnterpriseContactForm = ({ strings }: EnterpriseContactFormProps) => { - const getCharacterCountClasses = (currentLength: number, maxLength: number) => - cn( - currentLength >= Math.floor(maxLength * 0.9) && "flex", // Show char count when within 10% remaining to limit - currentLength > maxLength - 64 && "text-warning-border", // Warning color within 64 chars (border version for proper contrast ratio), - currentLength > maxLength && "text-error [&_svg]:inline" // Error color over limit - ) - - const [formData, setFormData] = useState({ - email: "", - message: "", - }) - const [errors, setErrors] = useState({}) - const [submissionState, setSubmissionState] = - useState("idle") - - const handleInputChange = - (field: keyof FormState) => - (e: React.ChangeEvent) => { - const value = e.target.value - setFormData((prev) => ({ ...prev, [field]: value })) - - // Clear error when user starts typing - if (errors[field]) { - setErrors((prev) => ({ ...prev, [field]: undefined })) - } - } - - const handleBlur = - (field: keyof FormState) => - (e: React.FocusEvent) => { - const value = e.target.value - - if (field === "email") { - const emailError = validateEmail(value) - if (emailError) setErrors((prev) => ({ ...prev, email: emailError })) - return - } - if (field === "message") { - const messageError = validateMessage(value) - if (messageError) - setErrors((prev) => ({ ...prev, message: messageError })) - return - } - } - - const validateEmail = (email: string): React.ReactNode | undefined => { - const sanitized = sanitizeInput(email) - - if (!sanitized) return strings.error.required - - if (sanitized.length > MAX_EMAIL_LENGTH) return strings.error.emailTooLong - - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ - if (!emailRegex.test(sanitized)) return strings.error.emailInvalid - - const domain = sanitized.toLowerCase().split("@")[1] - if (CONSUMER_DOMAINS.includes(domain)) return strings.error.domain - - return undefined - } - - const validateMessage = ( - message: string - ): React.ReactNode | string | undefined => { - const sanitized = sanitizeInput(message) - - if (!sanitized) return strings.error.required - - if (sanitized.length > MAX_MESSAGE_LENGTH) - return strings.error.messageTooLong - - return undefined - } - - const validateForm = (): boolean => { - const newErrors: FormErrors = {} - - const emailError = validateEmail(formData.email) - if (emailError) newErrors.email = emailError - - const messageError = validateMessage(formData.message) - if (messageError) newErrors.message = messageError - - setErrors(newErrors) - return Object.keys(newErrors).length === 0 - } - - const handleSubmit = async () => { - if (!validateForm()) return - - setSubmissionState("submitting") - setErrors({}) - - try { - const sanitizedData = { - email: sanitizeInput(formData.email), - message: sanitizeInput(formData.message), - } - - const response = await fetch("/api/enterprise-contact", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(sanitizedData), - }) - - if (!response.ok) throw new Error(`Server error: ${response.status}`) - - setSubmissionState("success") - } catch (error) { - console.error("Form submission error:", error) - setSubmissionState("error") - setErrors({ general: strings.error.general }) - } - } - - if (submissionState === "success") - return ( -
-
- -

{strings.success.heading}

-
-

{strings.success.message}

-
- ) - - return ( -
-
- - {errors.email && ( -

- {errors.email} -

- )} -
- -
-
-