Skip to content

feat(library): add FAQPage JSON-LD to the eight keyword-research spokes - #240

Open
jeremypenguin-max wants to merge 1 commit into
every-app:mainfrom
jeremypenguin-max:library-faq-schema
Open

feat(library): add FAQPage JSON-LD to the eight keyword-research spokes#240
jeremypenguin-max wants to merge 1 commit into
every-app:mainfrom
jeremypenguin-max:library-faq-schema

Conversation

@jeremypenguin-max

Copy link
Copy Markdown
Contributor

What

Adds FAQPage JSON-LD to the eight keyword-research library spokes — 27 questions total. No other changes.

Spoke Q&A pairs
seed-from-conversation 3
long-tail-question-mining 3
search-intent-mapping 3
cluster-topical-hubs 3
gsc-programmatic-discovery 4
opportunity-sizing-forecasting 4
intent-beyond-google 4
positioning-to-demand 3
Total 27

Each file gets the same three things, copying the shape already used on the pillar (library/keyword-research/index.tsx): a faqs array, a faqLd object, and one dangerouslySetInnerHTML script. The component body is wrapped in a fragment so the script can sit beside <LibrarySpokePage>.

Why

The FAQ content already exists and is already visible on every one of these pages — a ## … FAQ H2 with ### questions and their answers, authored in the MDX. Only the markup was missing. The pillar page has emitted FAQPage since it shipped; the spokes never did.

How it was verified

The rule that matters here is that FAQ markup must match what is actually rendered — markup Google cannot see on the page is a violation, so a mismatched block would be worse than no block at all. So none of these strings were retyped:

  1. Extracted programmatically from the MDX. Question from the ### heading, answer from the paragraph beneath it. Inline markdown was resolved to the text a reader actually sees — inline-code backticks stripped (`noindex` renders as noindex), and link syntax reduced to its anchor text.
  2. Checked against the prerendered HTML, not the source. After vite build, every application/ld+json block was pulled out of each built page, JSON.parsed, and then every question and answer string was searched for verbatim inside the tag-stripped visible text of that same page.

Result: 27/27 pairs matched verbatim, 8/8 pages. Every page carries exactly two ld+json blocks — the new FAQPage and the BreadcrumbList that LibrarySpokePage already emitted — so there is no duplicate breadcrumb.

Checks:

  • npm --prefix web run types:check — clean
  • npx vite build — all eight spoke URLs prerender, no errors
  • npx prettier --check on the eight touched files — clean
  • Every JSON-LD block JSON.parses out of the built HTML

Scope notes

  • No prose changes, no new pages, no new dependencies.
  • No breadcrumb work: LibrarySpokePage already emits BreadcrumbList for these routes.
  • Does not depend on, and is not stacked on, any other open PR.
  • The same gap still exists on the competitive-analysis and site-audit spokes. Those live in unmerged PRs, so they are deliberately left out of this one; they can be covered once those merge.

🤖 Generated with Claude Code

Each spoke already renders a visible FAQ section, but only the pillar page
emitted FAQPage markup. This adds it to the eight spokes, 27 questions total.

The question/answer strings were extracted programmatically from each page's
MDX (H3 heading + the paragraph beneath it) rather than retyped, with inline
markdown resolved to the text a reader actually sees: backticks stripped from
inline code, link syntax reduced to its anchor text.

Every pair was then checked against the prerendered HTML: each ld+json block
JSON.parsed out of the built page, then every question and answer string
searched for verbatim in the tag-stripped visible text of that same page.
27/27 matched.

No prose changes and no breadcrumb changes - LibrarySpokePage already emits
BreadcrumbList for these routes.

Co-Authored-By: Claude Opus 5 (1M context) <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.

2 participants