@plesso/sanity-seo
v0.1.1
Published
Shared SEO substrate for Sanity-based content sites: seoMeta object, topicalCluster + promptTemplate doc types, programmatic readiness validator, Studio Document Actions (Generate Meta, Compute Readiness, Mark Reviewed, Suggest Internal Links, Verify Exte
Readme
@plesso/sanity-seo
Shared SEO substrate for Sanity-based content sites. Drop-in schemas, validators, and Studio Document Actions that give any Sanity-driven editorial site the same SEO substrate Plesso uses to drive surprisemywife and (eventually) every Plesso tenant.
Status
Phase 4.2 — sources lifted. All schemas, libs, and Studio Document Actions are in src/. The package builds in isolation. Phase 4.3 switches surprisemywife to consume it via workspace file: link.
What ships here
When fully lifted (4.2), this package exports:
Sanity object + doc types
seoMeta(object) — shared SEO metadata. Embeddable on any indexable doc type. Title, description, ogImage, canonical override, noindex flag, keywords, AI-generated chip, last-reviewed datetime, override reason.topicalCluster(doc) — hub-and-spoke editorial cluster. Carries the AI drafter config (queue, cadence, prompt template reference, monthly spend cap, telemetry).promptTemplate(doc) — reusable LLM prompts editable in Studio with manual version stamping for A/B.externalLinkAudit(doc) — programmatic broken-link tracker. One per source doc; updated by the audit endpoint + cron.
Studio Document Actions
ComputeSeoReadinessAction— programmatic validator. Zero LLM calls. Writes typed status + reason strings.MarkReviewedAction— stampsseoMeta.lastReviewedAt. Clears stale flag for 6 months.GenerateMetaFromBodyAction— AI-assisted (Claude Haiku). Proposes meta title + description from doc body; editor reviews + edits before publish.SuggestInternalLinksAction— deterministic ranker + checklist dialog. Per-link opt-in with editable anchor text.VerifyExternalLinksAction— single-doc broken-link audit. Surfaces in the sameexternalLinkAuditdoc type the cron walker uses.
Pure libraries
validateSeoReadiness(doc, cluster, opts)— pure validator. Ten required checks, seven advisory warnings, type-aware viarequireHub+requireInternalLinksoptions.rankAnchorCandidates+insertInternalLinks— deterministic scoring (keyword overlap × cluster match × recency × authority) + Portable Text span splitter.extractExternalLinks+checkUrl+auditDocLinks— broken-link audit primitives.
Install (Phase 4.3 onward)
pnpm add @plesso/sanity-seoPeers required (you almost certainly already have these in a Sanity project):
sanity>=3@sanity/client>=6.22@sanity/icons>=3@sanity/ui>=2react>=18
Usage (sketch — full docs land in Phase 4.2)
In your Sanity schemas index:
import {
seoMetaType,
topicalClusterType,
promptTemplateType,
externalLinkAuditType,
} from '@plesso/sanity-seo/schemas'
export const schemaTypes = [
// ... your verticals ...
seoMetaType,
topicalClusterType,
promptTemplateType,
externalLinkAuditType,
]Embedding seoMeta on a doc type:
import {defineType, defineField} from 'sanity'
export const myDocType = defineType({
name: 'myDoc',
type: 'document',
fields: [
// ... domain fields ...
defineField({name: 'seoMeta', type: 'seoMeta'}),
],
})Wiring the Document Actions to a doc type:
import {defineConfig} from 'sanity'
import {
ComputeSeoReadinessAction,
MarkReviewedAction,
GenerateMetaFromBodyAction,
} from '@plesso/sanity-seo/actions'
export default defineConfig({
// ...
document: {
actions: (input, context) => {
if (context.schemaType === 'myDoc') {
return [
...input,
GenerateMetaFromBodyAction,
ComputeSeoReadinessAction,
MarkReviewedAction,
]
}
return input
},
},
})Programmatic-first
Per the Plesso PRD: this package is mostly deterministic. The only LLM-touching action is GenerateMetaFromBodyAction (it makes one Claude call per invocation, editor-triggered). Everything else — readiness validation, link scoring, broken-link checks — is plain code. Reasons: cost, latency, debuggability, auditability.
License
UNLICENSED for now. Will likely move to MIT once the engine layer is open-sourceable as a standalone project (separate from the Plesso platform).
