Skip to content

fix: SEO indexing, duplicate content, robots.txt, and JSON-LD - #964

Merged
davidmytton merged 4 commits into
mainfrom
seo-indexing-fixes
Sep 26, 2026
Merged

davidmytton merged 4 commits into
mainfrom
seo-indexing-fixes

Conversation

@davidmytton

Copy link
Copy Markdown
Collaborator

Search Console reports 681 pages as "Excluded by 'noindex' tag". An audit of the build found that the noindex pages were the wrong ones, and the index was carrying empty duplicates.

Problems

  • No Python pages in Google. Every /sdk/:sdk/plus/:variant/ page was noindex and left out of the sitemap. Python has no base SDK route, and /sdk/python/* redirects to /sdk/python/plus/fastapi/*, so none of its 46 pages could be indexed. Express, Hono, and Bun + Hono had no indexable page either.
  • Empty copies in the index. The content loader copied every framework-specific page under every SDK and plus-variant prefix, whatever the page's frameworks frontmatter said. 218 copies had no framework content: SlotByFramework found no matching slot, so the page rendered an empty island, with no install command or code, even with JS. 142 of them were indexable and listed in the sitemap, for example /sdk/nuxt/rate-limiting/quick-start/.
  • Shared titles and descriptions. 217 indexable pages shared a title with a sibling copy, and 341 shared a meta description.

Changes

  • Only copy supported pages. The loader copies a page only to the SDKs listed in its frameworks.
    • The removed URLs are kept as a fixed list, RETIRED_SDK_DOC_ROUTES. Each one 301s to the base SDK's copy for a plus-variant (Express → Node.js), otherwise to the unscoped page.
    • The regenerated vercel.json no longer sends ?f= redirects to removed copies. The unscoped page reads ?f= itself.
    • The SDK switcher only offers SDKs the page supports.
    • Plus-variant sidebars and in-page links fall back to the base SDK's copy.
  • Index plus-variant pages. They drop noindex and are added to the sitemap. Unscoped legacy hubs stay noindex.
  • Unique titles and descriptions. SDK copies without a framework-specific title get " for " appended. Each framework-specific page gains an sdkDescription template, for example "Quick start guide for adding Arcjet rate limiting to your {sdk} app.", applied to description and og:description. Also fixes a typo and a wrong description on two pages.
  • robots.txt. Content-Signal is now search=yes, ai-input=yes, ai-train=yes.
  • JSON-LD. The logo, Organization, and SoftwareApplication nodes now match the site-wide graph on arcjet.com. The docs keep softwareHelp, which points at this site. offers is left out because arcjet.com only publishes it on /pricing.

Result

Before After
Rendered pages 679 461
Indexable pages 529 436
Plus-variant pages indexable 0 of 125 49 of 49
Pages sharing a title 217 0
Pages sharing a description 341 0

Testing

  • npm run build: 0 errors, 0 warnings.
  • npm run pw:run: 572 passed. New tests cover supported-copy selection, retired redirects, ?f= handling, switcher filtering, plus-variant indexability, the sitemap, and SDK descriptions.
  • A scan of every built page found no links to removed routes.
  • Screenshots: only the two /content-moderation/ Linux snapshots changed, because the "Last updated" date grew from Sep 3 to Sep 26. They were regenerated on aarch64, so the playwright-update.yml workflow can confirm them on amd64 if CI disagrees. The macOS snapshots for that page may also be stale for the same reason.

Not in this PR

  • Thin pages. /integrations/better-auth/ has no code since its example was removed from arcjet-js (#5633), and /regions/ is one paragraph. Both need content decisions.
  • 19 of the edited MDX files fail prettier --check, as they did on main before this change.

After deploy

Resubmit the sitemap in Search Console and click "Validate fix" on the noindex report. Expect about 25 URLs to remain, from the legacy hubs that are noindex on purpose.

🤖 Generated with Claude Code

Claude and others added 4 commits September 26, 2026 20:55
The logo, Organization, and SoftwareApplication nodes now copy the
site-wide graph on arcjet.com. The docs keep softwareHelp, which points
at this site.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The loader copied every framework-specific page under every SDK and
plus-variant prefix, whatever the page's `frameworks` frontmatter said.
218 copies had no framework content, 142 of them indexable, and they
were near-duplicates of each other with shared titles. The loader now
only copies a page to the SDKs it lists. The retired URLs are recorded
in RETIRED_SDK_DOC_ROUTES and 301 to the base SDK's copy (for a
plus-variant) or the unscoped page. Legacy `?f=` redirects no longer
point at them; the unscoped page reads `?f=` itself.

Plus-variant pages were all noindex and left out of the sitemap. With
the empty copies gone they are the only pages for Express, Hono, Bun +
Hono, FastAPI, and Flask, and Python has no other SDK routes at all, so
they are now indexable and listed.

SDK copies without a framework-specific title get the SDK name
appended, the SDK switcher only offers SDKs the page supports, and
plus-variant sidebars and links fall back to the base SDK's copy.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
SDK copies shared the unscoped page's description, which usually lists
several SDKs. 341 indexable pages had a description identical to a
sibling's. Framework-specific pages now set `sdkDescription`, a template
where `{sdk}` becomes the SDK label, and route middleware applies it to
the description and og:description tags. A page without one gets the
SDK named after its shared description.

Also fixes the "CAPCTCHAs" typo in the advanced signals description and
the signup protection reference description, which said email
validation.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@vercel

vercel Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
arcjet-docs Ready Ready Preview Sep 26, 2026 9:07pm UTC

Request Review

@arcjet-review arcjet-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arcjet Review — 🟡 Medium Risk

Decision: Needs Review

Rationale: The PR makes broad but mostly content/routing/SEO-oriented changes: SDK-scoped docs generation, sitemap inclusion, redirect generation, metadata mutation, robots.txt Content-Signal, and JSON-LD. I did not identify hardcoded secrets, user-input injection paths, auth logic changes, or critical security issues. However, the diff is large, includes a generated-looking vercel.json redirect rewrite and binary screenshot baselines, and correctness depends on the fixed RETIRED_SDK_DOC_ROUTES list and redirect ordering being complete. Because I cannot confidently validate all generated redirects and binary snapshots from the diff alone, human review is recommended before merge.

Summary of Changes

Updates docs SEO behavior by only publishing SDK copies for supported frameworks, indexing plus-variant SDK pages, adding per-SDK descriptions/titles, changing robots.txt to allow AI training, aligning JSON-LD entities with the main site, adding retired SDK route redirects, and expanding tests around sitemap, redirects, metadata, SDK switcher behavior, and snapshots.

Escalation Triggers

  • Authentication & Authorization: The diff contains the content pattern 'token' in AI/docs metadata text. This appears to refer to AI token budgets rather than authentication tokens, but the configured trigger matches diff content.

Review Focus Areas

Notes

The diff exceeds the configured 1000-line threshold, primarily because of the large vercel.json redirect changes and fixed retired route list; this reduces confidence in fully automated review. Security review found no secrets, auth implementation changes, injection sinks, cryptography changes, or sensitive data handling issues in the visible diff.

Review: b003afff | Model: openai/gpt-5.5 | Powered by Arcjet Review

@arcjet-review arcjet-review Bot added the needs review Awaiting human review label Sep 26, 2026
@davidmytton
davidmytton merged commit 818fa8a into main Sep 26, 2026
11 checks passed
@davidmytton
davidmytton deleted the seo-indexing-fixes branch September 26, 2026 21:31
@arcjet-review arcjet-review Bot removed the needs review Awaiting human review label Sep 26, 2026

This branch was successfully deployed

1 active deployment
Preview — 8923233a Deployed Sep 26, 2026 by vercel[bot]
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