logicsrc/apps/logicsrc-web/contract
Anthony Ettinger 61870aa481
seo: give every page its own social title, not the homepage's (#203)
Reddit, Slack, X and Facebook read og:title, and every page of
logicsrc.com was serving the homepage's. The <title> tag was correct per
page, which is why it went unnoticed: Next.js shallow-merges metadata, so
a page exporting only `{ title, description, alternates }` inherits the
root layout's `openGraph` object whole. og:title, og:description and
og:url were the homepage's on all 45 spec landing pages, every doc, every
report and every SPA section.

Blog posts were the one route that declared openGraph, and they proved
the mechanism: their og:title is right. They also showed the other half
of it -- declaring openGraph drops the file-convention opengraph-image,
so live posts shipped with no og:image at all, and their twitter:title
was still the homepage's.

- src/lib/page-meta.ts: one builder, three entry points. specMetadata
  titles a spec landing page from its lib/specs.ts entry, pageMetadata
  titles the site's own pages from PAGE_META, contentMetadata titles a
  doc, post, skill or ontology record from its content. All three always
  emit openGraph and twitter title, description, url and image.
- Spec titles come from the registry, so they cannot drift from the way
  the sidebar, /specs and the home page describe the same spec, and a new
  spec page is titled the moment its registry entry exists. composeTitle
  trims a long subject line at a clause boundary to fit a link preview.
- Doc pages carry that subject line too, because every spec's H1 is just
  its name: "OpenStream" alone was the whole title.
- docExcerpt joins the wrapped lines of the first real paragraph and
  skips Status:/Slug: headers and list lead-ins, so descriptions stopped
  being "Status: 0.1 draft" and "Core tables:".
- contract/page-metadata.contract.test.ts fails if a sitemap route has no
  title, if a spec page has no registry entry, if two pages share a
  title, if a page declares metadata without the builder, or if a page
  loses its social image.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-24 01:00:25 -07:00
..
apex-rewrites.contract.test.ts OpenFleet: agents under a human, the record of who spawned whom, and the ledger the sysop reads 2026-09-13 08:15:03 +00:00
html-sanitizer.test.ts
install-command.contract.test.ts feat(web): put the one-line install in front of everyone 2026-07-30 12:55:30 -07:00
logicsrc-web.contract.test.ts Check agent-hour units in checkout validation 2026-09-13 09:35:14 +00:00
marketing-drift.contract.test.ts Add SSH keys and config to credential sharing (#139) 2026-08-13 17:03:00 -07:00
ontology-api.contract.test.ts fix(web): validate ontology pagination (#138) 2026-08-10 18:59:16 -07:00
openskill.contract.test.ts Add OpenSkill descriptions for human capabilities and OpenProfile discovery 2026-09-13 15:47:58 +00:00
openstack.contract.test.ts docs: OpenStack.md 0.1, one Markdown file for what a project is built on (#191) 2026-09-21 02:21:12 -07:00
page-metadata.contract.test.ts seo: give every page its own social title, not the homepage's (#203) 2026-09-24 01:00:25 -07:00
spec-discovery.contract.test.ts feat(specs): OpenObject and OpenSlice 0.1 (#192) 2026-09-21 03:05:38 -07:00