Skip to content

seo: stop emitting a second, @id-less Organization - #11

Merged
JasonColapietro merged 1 commit into
mainfrom
claude/entity-canon
Aug 31, 2026
Merged

seo: stop emitting a second, @id-less Organization#11
JasonColapietro merged 1 commit into
mainfrom
claude/entity-canon

Conversation

@JasonColapietro

Copy link
Copy Markdown
Collaborator

The homepage described the company twice, and neither could merge

src/app/layout.tsx defines the real Organization under SUEDE_ORG_ID. src/lib/seo.ts separately emitted an inline publisher with a name and url but no @id at all:

publisher: { '@type': 'Organization', name: 'Suede Labs AI', url: 'https://suedeai.ai' },

An Organization with no @id cannot join the graph. So the page asserted the company twice and gave a reconciler nothing to merge on — this is why an estate sweep read dna.suedeai.ai as having an Organization with a missing @id.

The publisher is now a reference to the canonical node, which is what a publisher should be:

publisher: { '@id': 'https://suedeai.ai/#organization' },

And the real definition is now complete

layout.tsx's Organization gains foundingDate: "2024" and the canonical sameAs set including Wikidata Q141169484 — present on only 4 of 34 hosts when the estate was measured on 2026-08-31.

Checks

Both files verified brace- and bracket-balanced. There's no node_modules in this checkout, so typecheck and test run in CI rather than locally — flagging that rather than implying I ran them.

The homepage rendered two Organization nodes. src/app/layout.tsx defines
the real one under SUEDE_ORG_ID; src/lib/seo.ts separately emitted an
inline publisher with a name and a url but no @id at all. An Organization
with no @id cannot join the graph, so the homepage described the company
twice and let a reconciler merge neither.

The publisher in seo.ts is now a reference to the canonical @id, which is
what a publisher should be. The definition in layout.tsx gains
foundingDate 2024 and the canonical sameAs set, including the Wikidata
item Q141169484 -- present on only four of thirty-four hosts when the
estate was measured on 2026-08-31.

Both files verified brace- and bracket-balanced. No local toolchain in
this checkout, so typecheck and tests run in CI.
@JasonColapietro
JasonColapietro merged commit 77b6721 into main Aug 31, 2026
1 check passed
@JasonColapietro
JasonColapietro deleted the claude/entity-canon branch August 31, 2026 08:58
JasonColapietro added a commit that referenced this pull request Sep 3, 2026
…12)

* ci: fail the deploy when it cannot deploy, and prove the alias moved

dna.suedeai.ai has not been serving main. Live right now, the Organization
node carries no foundingDate and the page ships two JSON-LD blocks; main sets
foundingDate '2024' and consolidated the graph in #11 (77b6721, 2026-08-31).
The commit merged, the Actions tab went green, and nothing shipped.

Two causes, both fixed here.

1. The credential check set `ready=false` when VERCEL_TOKEN was missing and
   every later step carried `if: steps.creds.outputs.ready == 'true'`. So the
   job skipped its way to success. A deploy workflow that cannot deploy is a
   failure, not a skip. It now checks all three secrets, writes which are
   missing to the step summary, emits ::error:: and exits 1. The nine dead
   per-step guards are gone with it.

2. "Verify production is serving" only asserted a 200. The host answered 200
   throughout the entire period when main was never deployed, so that check
   could never have caught this. Next chunk filenames are content-hashed, so
   the step now pulls the chunk set from both the deployment just created and
   from dna.suedeai.ai and requires them to match - which is the thing we
   actually care about: did the production alias move to this build. If the
   deployment URL cannot be read it warns rather than failing, so a genuine
   deploy is never failed by a flaky fetch.

Verified: the workflow parses as YAML, the new verify step passes `bash -n`,
and the chunk-extraction logic was dry-run against the live site (7 chunks,
self-comparison matches).

This does not by itself put main on production - the repository still has no
VERCEL_TOKEN, VERCEL_ORG_ID or VERCEL_PROJECT_ID. That needs someone with
admin on Suede-AI/dna to add them under Settings -> Secrets and variables ->
Actions, then run this workflow via workflow_dispatch. The difference is that
until that happens the workflow will say so in red instead of green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* seo: point the LinkedIn sameAs at the URL LinkedIn redirects to

https://www.linkedin.com/company/suede-labs-ai 301s to
https://www.linkedin.com/company/suede-labs. LinkedIn only redirects a vanity
slug within the same company page, so the destination is the current canonical
URL for the page this estate already claims.

It matters more than an ordinary redirect because most of these occurrences
are in JSON-LD `sameAs`, the field search and answer engines use to decide
which accounts belong to the same entity. An entity's identity links should
resolve directly rather than through a hop.

Confirmed with the owner (2026-09-03) that the destination page is theirs.

Part of an estate-wide sweep: 82 occurrences across 16 repos, verified to be
the only line changed in every file. Occurrences inside
JasonColapietro/suede-geo's docs/seo-audits/ are deliberately left alone -
those are dated records of what an earlier audit saw, and they are not
published.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant