From c92ef2b3fe765a19e768ac0146fa5234283af95f Mon Sep 17 00:00:00 2001 From: Florent Tapponnier Date: Sat, 25 Jul 2026 22:14:21 +0200 Subject: [PATCH] jsonld: replace remaining @id-only refs with Thing/inline (fix chain + alt pages) Deep-check after PR #1442 caught 4 more @id-only refs Google could flag as standalone incomplete Datasets: - benchmarks/[slug]/[chain] TechArticle: about + isPartOf (cross-page refs to parent bench Dataset + Article). about becomes {@type:Thing, name: metric}; isPartOf gets name+url inlined. - benchmarks/[slug] TechArticle: about (same-page but Google flagged even same-graph refs). Becomes {@type:Thing, name: metric}. - alternatives/[slug] Article: about (same-page). Becomes {@type:Thing, name: bench.metric}. Semantically cleaner too: 'about' on an article should describe the topic (Thing), not a data source. Matches the pattern already used by StatisticalReport.about. --- src/app/alternatives/[slug]/page.tsx | 5 ++++- src/app/benchmarks/[slug]/[chain]/page.tsx | 16 ++++++++++++++-- src/app/benchmarks/[slug]/page.tsx | 7 ++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/app/alternatives/[slug]/page.tsx b/src/app/alternatives/[slug]/page.tsx index 73df1a31..f58b3563 100644 --- a/src/app/alternatives/[slug]/page.tsx +++ b/src/app/alternatives/[slug]/page.tsx @@ -159,7 +159,10 @@ export default async function AlternativePage({ ...(citableAsOf(bench) ? { dateModified: bench.lastRunAt } : {}), author: { "@id": `${SITE.url}/#org` }, publisher: { "@id": `${SITE.url}/#org` }, - about: { "@id": `${url}#dataset` }, + // `about` describes the topic. Use a Thing rather than @id-refing + // the same-page Dataset (Google validates @id-only refs as + // standalone incomplete Datasets even within the same @graph). + about: { "@type": "Thing", name: bench.metric }, }, buildBreadcrumbJsonLd([ { name: "Home", item: SITE.url }, diff --git a/src/app/benchmarks/[slug]/[chain]/page.tsx b/src/app/benchmarks/[slug]/[chain]/page.tsx index 61b993c5..7564acef 100644 --- a/src/app/benchmarks/[slug]/[chain]/page.tsx +++ b/src/app/benchmarks/[slug]/[chain]/page.tsx @@ -375,8 +375,20 @@ export default async function BenchmarkChainPage({ author: [{ "@id": PERSON_ID }, { "@id": `${SITE.url}/#org` }], reviewedBy: { "@id": PERSON_ID }, publisher: { "@id": `${SITE.url}/#org` }, - about: { "@id": `${benchmarkUrl}#dataset` }, - isPartOf: { "@id": `${benchmarkUrl}#article` }, + // `about` describes the topic. Point at the metric as a Thing + // rather than @id-referencing the parent bench Dataset (cross-doc + // @id refs get validated as standalone incomplete Datasets by + // Google, same class of issue as the isPartOf/isBasedOn fixes). + about: { "@type": "Thing", name: benchmark.metric }, + // isPartOf: parent bench article. Inline the required fields so + // the reference validates on its own (Google does not stitch + // cross-page @id refs). + isPartOf: { + "@type": "TechArticle", + "@id": `${benchmarkUrl}#article`, + name: benchmark.title, + url: benchmarkUrl, + }, }, buildBreadcrumbJsonLd([ { name: "Home", item: SITE.url }, diff --git a/src/app/benchmarks/[slug]/page.tsx b/src/app/benchmarks/[slug]/page.tsx index 966eda10..a7170b75 100644 --- a/src/app/benchmarks/[slug]/page.tsx +++ b/src/app/benchmarks/[slug]/page.tsx @@ -419,7 +419,12 @@ export default async function BenchmarkPage({ author: [{ "@id": PERSON_ID }, { "@id": `${SITE.url}/#org` }], reviewedBy: { "@id": PERSON_ID }, publisher: { "@id": `${SITE.url}/#org` }, - about: { "@id": `${benchmarkUrl}#dataset` }, + // `about` describes the topic. Use a Thing (matches the + // StatisticalReport `about` pattern above) rather than @id-refing + // the same-page Dataset. Google's Dataset validator was flagging + // @id-only refs as standalone incomplete Datasets even within + // the same @graph (see the isBasedOn fix in dataset-jsonld.ts). + about: { "@type": "Thing", name: benchmark.metric }, }, buildBreadcrumbJsonLd([ { name: "Home", item: SITE.url },