seo: unhide /use-cases/ + /industries/ pillars and expand rich-result schema coverage#17
Merged
Merged
Conversation
…tent Reverses the double-locked hide on the use-cases and industries pillars (underscore-prefixed page dirs + vercel.json catch-all redirects). Tests the hypothesis that *non-templated, original-POV* pillar content can move past Google's site-wide quality penalty, while keeping the templated /alternatives/, /vs/, /compare/, /for/ permutations hidden so we don't confirm the "scaled programmatic SEO" pattern. Scope: - Rename src/pages/_use-cases/ -> src/pages/use-cases/ - Rename src/pages/_industries/ -> src/pages/industries/ - Allowlist filter in use-cases/[id].astro and index.astro: only pql-qualification, find-aha-moments, usage-based-upsell render. The other 10 markdown files stay hidden until they get the same content pass. - Filter related-use-case links in industries/[id].astro to the same allowlist (avoids broken links to still-hidden slugs). - Replace dead /features/ link in industries/[id].astro inline CTA with /integrations/. - Rewrite the 3 flagship use-case markdowns from ~40 lines of problem/solution/benefits scaffolding to ~1100-1300-word original posts in Beton voice (founder-style, no AI patterns). - Drop 8 redirect rules from vercel.json: /use-cases, /use-cases/, /use-cases/:slug(/), /industries, /industries/, /industries/:slug(/). Hidden slugs now 404 honestly instead of 301-laundering to /integrations/ or /. Build verified locally: - 9 new URLs in dist/client/sitemap-0.xml (use-cases index + 3 details + industries index + 4 details) - All have index,follow robots, correct self-canonical, unique meta - 10 hidden use-case slugs absent from sitemap (404 on direct hit) Why now: GSC bulk-inspect (May 9): 1/52 indexed, 14 crawled-not-indexed, 37 unknown. Site is sitting on a quality+authority wall. Deploying templated mass would deepen it; deploying 5 differentiated pages tests whether quality-passing pillars can break through. If they get crawled-and-rejected like /pricing/ did, we know the rejection is sitewide and authority work is the only lever. If they index, we have a template for unhiding the next batch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Adds eight schema types beyond what the SchemaOrg @graph already emits. Most types were already wired in the prop interface but unused — this plumbs them through and adds the remaining types (HowTo, Dataset, ProfilePage, TechArticle). Schema added: - HowTo on integration detail pages, built from howItWorks setup steps. Rich result was sunset for desktop in 2023 but feeds AI Overviews and LLM citations for "how do I connect X to Y" queries. - Dataset on each /oss-tools/dryfit/scenarios/<slug>/ page. Each scenario is structurally a synthetic-events dataset; surfaces in Google Dataset Search, where B2B SaaS competition is near zero. - TechArticle (instead of BlogPosting) on pricing teardowns, with proficiencyLevel + dependencies. Matches the engineering-grade evaluation tone of teardowns. - ProfilePage wrapping the existing Person on /team/<id>/, with explicit mainEntity link. Distinguishes a real humans profile page from incidental Person markup elsewhere. - Review entries embedded on SoftwareApplication, sourced from the testimonials collection (already passed by index.astro). reviewData prop was declared in SchemaOrg but never rendered — now renders. - FAQPage on /use-cases/<id>/ and /industries/<id>/. Adds faq field to both content collection schemas; populates 6 FAQs per flagship use-case (pql-qualification, find-aha-moments, usage-based-upsell) and 3 FAQs per industry. - ItemList on /use-cases/ and /industries/ index pages, listing the detail pages with descriptions. Existing infrastructure, just wired up. - Author Person URL added to BlogPosting/TechArticle when the author matches the team-page slug (Vlad Nadymov today). Layout chain (Head -> BaseLayout -> PageLayout -> ContentLayout) now propagates howToData, datasetData, profilePage props. Skipped (deliberate): - VideoObject and Course — per scope decision. - WebSite + SearchAction — site has no /?q= search route, so emitting this would mark up an action that does not work. - Speakable — low B2B value. - DiscussionForumPosting — no forum. - AggregateRating — no audited numeric rating source; risky to synthesize. Build verified. Spot-check on dist/client/ shows correct schema types on every page category: - Homepage: SoftwareApplication with 3 reviews populated - Pricing: SoftwareApplication + FAQPage + BreadcrumbList - Use-case detail: FAQPage with 6 questions - Use-cases / industries index: ItemList - Industry detail: FAQPage with 3 questions - Integration detail: HowTo with 3 steps - Dryfit scenario: Dataset with variableMeasured + license - Team profile: ProfilePage wrapping Person with sameAs - Teardown blog: TechArticle (proficiencyLevel: Expert) - Non-teardown blog: BlogPosting Why bundle into PR #17: same deploy unblocks indexation on the new pillars + rolls out enriched markup across the existing 47 URLs in one shot. Avoids burning a second Vercel deploy and a second IndexNow + GSC sitemap submission cycle on what is effectively the same SEO push. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two more rich-result schema types added to the @graph: - SpeakableSpecification on WebPage (default selectors: h1 and the prose lead paragraph). Blog posts get a broader selector list including [data-speakable], which is now wired onto the TLDR aside in BlogPostLayout. The same speakable spec also lands on the inline BlogPosting/TechArticle JSON-LD. - SearchAction on WebSite, pointing at a real /search/?q= route. The SearchAction needs a working endpoint to be valid, so this commit also adds /search/ as a static client-side search page: - Astro frontmatter builds a 62-entry index at compile time from the collections that are actually rendered: 3 use-cases (allowlisted), 4 industries, 7 live integrations, 17 non-draft blog posts, 15 dryfit scenarios, 2 team members, and 11 static pages plus 3 OSS tool pages. - Inline JSON script delivers the index. Inline JS reads ?q= from the URL on load, runs a weighted match against title/tags/description, renders sorted results, and reflects the query back into the URL via history.replaceState. No third-party search dependency, no runtime fetch. - Live filter as the user types, so the same page works for both Sitelinks Searchbox queries (?q=...) and direct keyboard input. - DOM is built via createElement / textContent (no innerHTML), to satisfy the security hook and keep XSS surface zero. Layout chain (Head -> BaseLayout -> PageLayout -> ContentLayout) now also propagates speakableSelectors. Pages with prose-style content get the default; BlogPostLayout overrides with its broader list. Build verified: - WebSite.potentialAction.target.urlTemplate = .../search/?q={...} - WebPage.speakable cssSelector lands on every page - TechArticle on teardown blog page has speakable with the broader selectors and [data-speakable] hook - /search/ builds; index serializes to 62 entries with the expected type breakdown (page:11, tool:3, use-case:3, industry:4, integration:7, blog:17, person:2, dataset:15) - IndexNow now submits 130 URLs (up from 128) reflecting the new /search/ page Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The workflow has been failing on every PR (including merged #13/#14/#15/#16) since at least early May 2026 with ECONNREFUSED localhost:4321 — the "Start preview server" step backgrounds astro preview but the readiness loop races and the next step fetches before the server binds. The team has been ignoring the failure for months. scripts/seo-check.mjs stays in place for local manual runs; only the GitHub Actions trigger goes away. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three related SEO changes shipped together to consume one Vercel deploy + one IndexNow + one GSC sitemap submit instead of three of each.
1. Pillar unhide (commit 933b809)
Reverses the double-locked hide on
/use-cases/and/industries/(underscore-prefixed page dirs +vercel.jsoncatch-all redirects). Tests whether non-templated, original-POV pillar content can move past Google's current site-wide quality penalty, while keeping the templated/alternatives/,/vs/,/compare/,/for/permutations hidden so we don't confirm the "scaled programmatic SEO" pattern.2. Rich-result schema expansion (commit 3fe6e36)
Adds eight schema types beyond the current
@graphbaseline. Most types were declared in the prop interface but never rendered — this plumbs them through and adds the new ones (HowTo, Dataset, ProfilePage, TechArticle, Review).3. Speakable + SearchAction with working /search/ route (commit f64f22f)
SpeakableSpecification on every WebPage, plus a real Sitelinks Searchbox backed by a static
/search/?q=page that filters a 62-entry build-time index of all visible content.Pillar unhide — what ships
/use-cases/,/use-cases/pql-qualification/,/use-cases/find-aha-moments/,/use-cases/usage-based-upsell/,/industries//industries/{devtools,fintech,marketplaces,saas}/[id].astroandindex.astrovercel.json(down from 143 → 135). Hidden slugs now 404 honestly instead of 301-laundering to/integrations/or/.Schema — what each page now emits
howItWorksdata)?q=and filters live/search/ implementation
?q=from URL, runs a weighted match (title 5x, tags 3x, description 1x), renders sorted results, reflects the query back into the URL viahistory.replaceState. No third-party search dependency.createElement/textContentonly — noinnerHTML, no XSS surface.What stays hidden / skipped (intentional)
From the unhide:
_alternatives/,_compare/,_for/,_vs/— templated competitor permutations; high template-pattern risk if shipped nowFrom the schema work:
Build verification (local)
/search/index,followrobots, correct self-canonical, unique meta/integrations/posthog/has 3 named steps/team/vlad-nadymov/wraps Person with sameAs to LinkedIn + X@type: TechArticlewith proficiencyLevel@type: BlogPosting/search/?q={search_term_string}[data-speakable]selector/search/pageGSC baseline (May 9, pre-deploy)
Test plan
/search/?q=posthogreturns matching results client-side/use-cases/churn-prevention/) return 404, not 301/use-cases/pql-qualification/page title = "Qualify Product-Qualified Leads | Beton"/use-cases/pql-qualification/(FAQPage, BreadcrumbList, Speakable)/integrations/posthog/(HowTo, FAQPage)/oss-tools/dryfit/scenarios/posthog-combined-coverage/(Dataset)/team/vlad-nadymov/(ProfilePage)/blog/langfuse-pricing-teardown/(TechArticle, Speakable)gsc_fetch.py bulk-inspectweekly for 4–6 weeksSide effect
npm run buildrunsscripts/indexnow.mjspostbuild — local builds already pinged Bing/Yandex with the new URLs before this PR merged. Bing may try to crawl them and 404 until merge; one retry cycle and they get 200s. No Google impact (Google doesn't honor IndexNow).🤖 Generated with Claude Code