Skip to content

schema: make Organization node resolvable on Article/TechArticle pages - #20524

Merged
CamSoper merged 1 commit into
masterfrom
seo/resolvable-organization-node
Jul 27, 2026
Merged

schema: make Organization node resolvable on Article/TechArticle pages#20524
CamSoper merged 1 commit into
masterfrom
seo/resolvable-organization-node

Conversation

@workprentice

@workprentice workprentice Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a minimal, resolvable Organization node to the JSON-LD @graph on every non-homepage page (blog posts, docs pages, comparison pages, etc.) so that the publisher (and other) @id references those pages already emit actually resolve to concrete data.

Why

BlogPosting, TechArticle, and other Article-type nodes emit publisher (and related fields) as a bare reference:

"publisher": {"@id": "https://www.pulumi.com/#organization"}

That @id only resolves to concrete data (name, logo) when the same page's JSON-LD @graph also defines an Organization node with that @id — but today only the homepage does. Google (and other structured-data consumers) evaluate each URL's JSON-LD independently and do not dereference @id links across pages, so publisher.name (required by schema.org/Article) and publisher.logo (recommended for rich results and AI citation) have been effectively undefined on every blog post and docs page site-wide, including Pulumi's most AI-cited page (/blog/infrastructure-as-code-tools/).

This is a single change to the shared graph-builder partial, so it fixes the entire blog + docs corpus (thousands of pages) at once — the same "fix once, apply everywhere" pattern as the FAQPage/ItemList schema work shipped in #20499/#20522/#20413.

What changed

  • layouts/partials/schema/graph-builder.html: in the {{ else }} branch (i.e. every page that is not the homepage), append a minimal Organization node — @type, @id, name, alternateName, url, logo (as an ImageObject) — copied verbatim from the homepage's existing Organization node values, so the entity stays consistent site-wide.
  • The homepage keeps its existing full corporate entity (founders, address, sameAs, etc.) completely unchanged; it is not touched by this change and does not receive a duplicate node.

Verification

  • Ran a local Hugo build (hugo --minify equivalent via hugo server-style build) covering the homepage, a representative blog post (/blog/infrastructure-as-code-tools/), and a representative docs page (/docs/iac/concepts/).
  • Confirmed on the blog post and docs page: the @graph now contains exactly one Organization node (@id https://www.pulumi.com/#organization, name "Pulumi Corporation", logo present as an ImageObject), and publisher.@id on the BlogPosting/TechArticle node matches it.
  • Confirmed on the homepage: still exactly one Organization node (the existing full corporate entity) — no duplicate was introduced.
  • Confirmed all JSON-LD blocks parse as valid JSON.
  • git diff --stat confirms exactly one file changed (layouts/partials/schema/graph-builder.html, +28 lines, 0 removed) — purely additive, no existing logic touched.

#new-review

@claude please review


🧠 This PR was created by workprentice via automated technical-SEO agent on behalf of the Pulumi marketing/growth workspace.

BlogPosting, FAQPage, and TechArticle nodes emit publisher (and related
fields) as a bare {"@id": "https://www.pulumi.com/#organization"}
reference. That @id only resolves to concrete data (name, logo) when the
same page's JSON-LD @graph also defines the Organization node — but only
the homepage does. Structured-data parsers evaluate each URL's JSON-LD
independently and do not dereference @id links across pages, so
publisher.name (required by schema.org/Article) and publisher.logo
(recommended for rich results) have been undefined on every blog post and
docs page.

This adds a minimal, resolvable Organization node (name, url, logo) to
the @graph on every non-home page, with values copied verbatim from the
homepage's node so the entity stays consistent site-wide. The homepage
keeps its existing full corporate entity (founders, address, sameAs,
etc.) unchanged and does not get a duplicate node.

Verified via local Hugo build: publisher @id now resolves to a concrete
Organization node with name + logo on both a blog post
(/blog/infrastructure-as-code-tools/) and a docs page
(/docs/iac/concepts/), while the homepage still emits exactly one
Organization node.
@github-actions github-actions Bot added review:triaging Claude Triage is currently classifying the PR domain:infra PR touches workflows, scripts, infra, Makefile, or build config review:in-progress Claude review is currently running and removed review:triaging Claude Triage is currently classifying the PR labels Jul 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Pre-merge Review — Last updated 2026-07-26T12:45:37Z

Tip

Summary: This is an infrastructure/template change to the JSON-LD structured-data builder (layouts/partials/schema/graph-builder.html). It adds an {{ else }} branch so every non-home page emits a minimal, resolvable Organization node (name/url/logo) under the shared @id https://www.pulumi.com/#organization, which the page's article/TechArticle publisher/author fields already reference as a bare @id. Previously those references had no resolvable target on non-home pages, so publisher.name (required by schema.org/Article) and publisher.logo were undefined off the homepage. The kind of wrongness that would matter here is malformed JSON-LD, a mismatched @id/value drift from the canonical homepage node, or an unintended duplicate Organization node — I confirmed the branch is syntactically well-formed Go-template dict/slice construction, the @id matches the reference target, and every value (@type, name, alternateName, url, logo dims 600×60) is copied verbatim from the homepage $org node, trimmed only of the corporate-detail fields the comment intentionally omits. I reviewed the template logic and cross-checked it against the homepage Organization node in the same file; no external factual claims required verification.

Review confidence:

Dimension Level Notes
mechanics HIGH
facts HIGH No external factual claims; the four extracted items are internal JSON-LD schema values, verified against the homepage node in the same file.
Investigation log
  • Cross-sibling reads: not run (not in a templated section)
  • External claim verification: 0 of 4 claims verified (0 unverifiable, 0 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 4 Pass 1, 0 Pass 2, 0 Pass 3.
  • Cited-claim spot-checks: not run (no cited claims)
  • Frontmatter sweep: not run (no frontmatter in diff)
  • Temporal-trigger sweep: not run (no trigger words)
  • Code execution: not run (no static/programs/ change)
  • Code-examples checks: not run (no fenced code blocks in content files)
  • Editorial-balance pass: not run (not under content/blog/)
🚨 Outstanding ⚠️ Low-confidence 💡 Pre-existing ✅ Resolved
0 0 0 0

🔍 Verification trail

4 claims extracted · 0 verified · 0 unverifiable · 0 contradicted
  • L247 in layouts/partials/schema/graph-builder.html "fields as a bare {'@id': 'https://www.pulumi.com/#organization'} reference," → ➖ not-a-claim (evidence: This is a code comment in graph-builder.html describing the PR author's own JSON-LD schema design: it explains that article-entity.html emits publisher/author/citation fields as a bare {"@id": "https://www.pulumi.com/#organization"} refe…; source: repo:layouts/partials/schema/graph-builder.html)
  • L260 in layouts/partials/schema/graph-builder.html "'@id' 'https://www.pulumi.com/#organization'" → ➖ not-a-claim (evidence: The line "@id" "https://www.pulumi.com/#organization" is a JSON-LD identifier used internally by the site's own structured-data schema graph (confirmed by surrounding code and comments explaining the design rationale), not a factual asse…; source: repo:layouts/partials/schema/graph-builder.html)
  • L263 in layouts/partials/schema/graph-builder.html "'url' 'https://www.pulumi.com'" → ➖ not-a-claim (evidence: Line 263 is "url" "https://www.pulumi.com" inside a Hugo template building a JSON-LD Organization schema object ($orgMinimal), matching the identical field on line 113 in the homepage Organization entity. This is structured-data source…; source: repo:layouts/partials/schema/graph-builder.html)
  • L266 in layouts/partials/schema/graph-builder.html "'url' 'https://www.pulumi.com/logos/brand/logo.png'" → ➖ not-a-claim (evidence: This is a hardcoded logo URL used in the site's own JSON-LD structured-data template, copied verbatim from the homepage's Organization node (line 116) as the comment at line 256 explains. It's the author's own asset reference, not a falsif…; source: repo:layouts/partials/schema/graph-builder.html)

🚨 Outstanding in this PR

No outstanding findings in this PR.

⚠️ Low-confidence

No low-confidence findings.

💡 Pre-existing issues in touched files (optional)

No pre-existing issues in touched files.

✅ Resolved since last review

No items resolved since the last review.

📜 Review history

  • 2026-07-26T12:45:37Z — No blockers: minimal Organization JSON-LD node added on non-home pages, values verified verbatim against the homepage node; no factual claims to check. (b2ccb64)

Need a re-review? Want to dispute a finding? Mention @claude and include #update-review.
(For ad-hoc questions or fixes, just @claude — no hashtag.)

@github-actions github-actions Bot added review:no-blockers Claude review completed cleanly; outstanding is empty and removed review:in-progress Claude review is currently running labels Jul 26, 2026
@pulumi-bot

Copy link
Copy Markdown
Collaborator

@pulumi-bot

Copy link
Copy Markdown
Collaborator

Lighthouse Performance Report

Commit: b2ccb64 | Metric definitions

Page Device Score FCP LCP TBT CLS SI
Homepage Mobile 🔴 34 4.0s 14.2s 2366ms 0.001 5.9s
Homepage Desktop 🟡 83 0.8s 1.1s 292ms 0.017 1.6s
Install Pulumi Mobile 🟡 59 6.2s 9.8s 106ms 0.053 6.2s
Install Pulumi Desktop 🟡 83 1.4s 2.1s 0ms 0.015 1.8s
AWS Get Started Mobile 🟡 55 6.0s 9.5s 70ms 0.086 8.4s
AWS Get Started Desktop 🟡 79 1.4s 2.0s 0ms 0.019 3.0s

@CamSoper CamSoper left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated rubber stamp approval applied :shipit:


Generated by Claude Code

@CamSoper
CamSoper merged commit e5e34b7 into master Jul 27, 2026
12 checks passed
@CamSoper
CamSoper deleted the seo/resolvable-organization-node branch July 27, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:infra PR touches workflows, scripts, infra, Makefile, or build config review:no-blockers Claude review completed cleanly; outstanding is empty

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants