Skip to content

seo: fix Moz and GSC flags via server-side redirects and noindex headers#874

Closed
Jordy-Baby wants to merge 1 commit into
mainfrom
claude/nifty-diffie
Closed

seo: fix Moz and GSC flags via server-side redirects and noindex headers#874
Jordy-Baby wants to merge 1 commit into
mainfrom
claude/nifty-diffie

Conversation

@Jordy-Baby
Copy link
Copy Markdown
Collaborator

@Jordy-Baby Jordy-Baby commented Apr 17, 2026

Summary

Fixes 40+ SEO issues flagged by Moz and Google Search Console through vercel.json config changes. No impact on production content or functionality.

Three changes to three files:

vercel.json (biggest change)

  • Replaces @docusaurus/plugin-client-redirects with 55 server-side 301 redirects. The plugin was generating thin HTML stubs with <meta http-equiv="refresh"> which Moz flagged for missing H1, thin content, meta refresh, and title issues. Server-side 301s are cleaner for SEO and users.
  • Adds 14 new redirect rules to clear GSC "Not Found (404)" errors — covers /blog/blog/* external-link typos, old /docs/HyperIndex/v2/* paths, wrong product combos, and legacy docs URLs.
  • Adds 9 X-Robots-Tag header rules to noindex low-value pages: blog tag pages, archive, RSS, pagination, and the HyperIndex-LLM / HyperSync-LLM / HyperRPC-LLM consolidated docs (which duplicate main docs content and were causing GSC "duplicate canonical" flags).

docusaurus.config.js

  • Removes the now-unused redirectsList array and @docusaurus/plugin-client-redirects plugin usage. File shrinks from 623 to 393 lines.

docusaurus.config.llm.js

  • Adds { name: "robots", content: "noindex, nofollow" } to themeConfig.metadata so the separate llm-docs.envio.dev build emits noindex on every page.

What this fixes

Moz (~30 issues cleared):

  • Pages with Missing/Invalid H1 — 12 docs URLs
  • Pages with Thin Content — 1 docs URL
  • Pages with Meta Refresh — 1 docs URL
  • Pages with Description Too Short — indirectly via noindex of affected pages

Google Search Console (~35 issues cleared):

  • Not Found (404) — 17 of 18 URLs now redirect (1 malformed URL unfixable)
  • Duplicate, Google chose different canonical — 1 URL (LLM-consolidated duplicates)
  • Crawled - currently not indexed — blog/tags/archive and LLM-LLM duplicates

What this does NOT change

  • No impact on production routing, canonical structure, or SEO metadata on real content pages
  • No new dependencies
  • The unused @docusaurus/plugin-client-redirects package is still in package.json but no longer imported — can be removed in a follow-up PR

Test plan

  • Full Docusaurus build passes locally (405 routes, no broken links)
  • All 55 redirect destinations verified to exist in build output
  • All 17 GSC 404 URLs simulated through redirect rules resolve correctly
  • MCP plugin still indexes all 405 documents
  • Verify on preview URL: click the Vercel preview link below and spot-check that pages load normally and redirects resolve
  • After deploy, click "Validate Fix" in Moz + GSC to accelerate re-crawl

Curl verification (optional, for devs)

Replace <preview> with the Vercel preview URL posted in PR comments:

# Redirects return 308 with correct Location
curl -sI https://<preview>/docs/overview | grep -iE "^(HTTP|location)"
curl -sI https://<preview>/blog/blog/envio-developer-update-january-2026 | grep -iE "^(HTTP|location)"

# Noindex headers present on tag/archive pages
curl -sI https://<preview>/blog/tags/ai | grep -i x-robots-tag
curl -sI https://<preview>/docs/HyperIndex-LLM/hyperindex-complete | grep -i x-robots-tag

# Regular pages still serve 200 with no noindex
curl -sI https://<preview>/docs/HyperIndex/overview | grep -iE "^(HTTP|x-robots-tag)"

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated search engine indexing directives for select documentation and blog pages
    • Implemented permanent URL redirects for documentation paths to maintain link continuity

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 17, 2026

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

Project Deployment Actions Updated (UTC)
envio-docs Ready Ready Preview, Comment Apr 29, 2026 2:28pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

📝 Walkthrough

Walkthrough

Removed client-side redirect configuration from the Docusaurus config file and added server-side redirects and SEO headers to vercel.json. Added a robots noindex/nofollow meta tag to the LLM config file. Redirects previously handled by Docusaurus plugin are now managed via Vercel's routing configuration.

Changes

Cohort / File(s) Summary
Docusaurus Configuration
docusaurus.config.js
Removed the redirectsList constant and @docusaurus/plugin-client-redirects plugin configuration (~229 lines), eliminating client-side redirect handling for legacy /docs/... paths and HyperIndex/HyperSync/HyperRPC mappings.
LLM Configuration
docusaurus.config.llm.js
Added robots meta tag with noindex, nofollow directive to the themeConfig.metadata array for SEO control.
Server Routing & Redirects
vercel.json
Added headers section applying X-Robots-Tag values to blog and docs patterns; introduced comprehensive redirects array with permanent URL mappings for blog paths and extensive docs rewrites to new /docs/HyperIndex/*, /docs/HyperSync/*, and /docs/HyperRPC/* routes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • llms.txt generation #706: Directly related—retrieves expanded redirectsList and client-redirects plugin setup that this PR removes from docusaurus.config.js.
  • Kv/fix 404 pages #738: Both modify the redirectsList configuration; this PR removes it while the other extends it.
  • Update messaging around tokens (RFC) #719: Inverse relationship—the retrieved PR preserves docusaurus.config.js redirect mappings that this PR deletes in favor of server-side Vercel routing.

Suggested reviewers

  • moose-code
  • nikbhintade

Poem

🐰 A hop through the redirects we go,
From client-side paths to Vercel's flow,
The robots now know: don't index, don't follow!
Legacy routes find new routes to swallow,
Configuration dances from one home to another,
Each redirect finds its perfect server-side brother! 🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title directly and concisely summarizes the main change: moving from client-side redirects to server-side redirects while adding noindex headers to fix SEO issues in Moz and Google Search Console.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/nifty-diffie

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
vercel.json (1)

51-121: Consider a smoke test in CI to catch redirect regressions.

69 permanent redirects is a lot of surface area to maintain by hand, and permanent: true means mistakes get cached hard by browsers and search engines. A small post-deploy check (or even a preview-deploy check) that curls each source and asserts a 301/308 to the expected destination would catch typos/conflicts before they hit prod. This can be a simple Node/bash script that reads vercel.json and hits the Vercel preview URL.

Not blocking — just a cheap safety net given the scope here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vercel.json` around lines 51 - 121, The redirects list in vercel.json (the
"redirects" array with many entries using "permanent": true) is high-risk; add a
CI smoke-test that reads vercel.json, iterates the "redirects" entries, and for
each {source,destination} verifies the deployed preview/prod URL for source
returns a 301/308 Location header matching destination. Implement as a small
script (e.g. verify-redirects.js or scripts/check-redirects.sh) that accepts a
base URL (preview via VERCEL_URL or CI-provided URL), performs HEAD/GET
requests, asserts the Location header equals the expected destination, and exit
non-zero on any mismatch; wire this script into CI (preview and/or post-deploy
job) to fail the pipeline on redirect regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@vercel.json`:
- Around line 34-37: The route entry "/blog/page/:path*" in vercel.json is inert
because Docusaurus is configured with postsPerPage: "ALL" in
docusaurus.config.js, so no paginated blog pages are emitted; either remove the
"/blog/page/:path*" rule to clean up the config or keep it intentionally as a
guard and add a concise comment explaining it is inactive while postsPerPage is
"ALL" so future maintainers understand why it exists.
- Around line 14-21: The vercel.json header rules use the wrong path
("/blog/tags" and "/blog/tags/:path*") so they don't match the actual Docusaurus
output where tagsBasePath is set to 'tag'; update the rules to target
"/blog/tag/:path*" (or add "/blog/tags/:path*" as an additional rule if you want
both) and remove the redundant explicit "/blog/tag" entry since ":path*" already
covers the index.

---

Nitpick comments:
In `@vercel.json`:
- Around line 51-121: The redirects list in vercel.json (the "redirects" array
with many entries using "permanent": true) is high-risk; add a CI smoke-test
that reads vercel.json, iterates the "redirects" entries, and for each
{source,destination} verifies the deployed preview/prod URL for source returns a
301/308 Location header matching destination. Implement as a small script (e.g.
verify-redirects.js or scripts/check-redirects.sh) that accepts a base URL
(preview via VERCEL_URL or CI-provided URL), performs HEAD/GET requests, asserts
the Location header equals the expected destination, and exit non-zero on any
mismatch; wire this script into CI (preview and/or post-deploy job) to fail the
pipeline on redirect regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cff29dd9-0176-4349-a1fa-206261bf1118

📥 Commits

Reviewing files that changed from the base of the PR and between ca9a5e8 and 8f4c033.

📒 Files selected for processing (3)
  • docusaurus.config.js
  • docusaurus.config.llm.js
  • vercel.json
💤 Files with no reviewable changes (1)
  • docusaurus.config.js

Comment thread vercel.json
Comment on lines +14 to +21
{
"source": "/blog/tags",
"headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
},
{
"source": "/blog/tags/:path*",
"headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
},
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP --type=js -C2 '\btagsBasePath\b'
# Also list what the build actually emits for tag pages:
rg -nP --type=js -C2 '\barchiveBasePath\b|\bpageBasePath\b'

Repository: enviodev/docs

Length of output: 281


Blog tag noindex rules target the wrong path — they will not match actual tag URLs.

In docusaurus.config.js the blog plugin is configured with tagsBasePath: 'tag' (singular). That means Docusaurus emits blog tag pages at:

  • /blog/tag (index)
  • /blog/tag/<tagname>

…not /blog/tags/.... As written, these two header rules match nothing in the produced site, so the tag pages (one of the specifically called-out low-value/duplicate targets in the PR description) will continue to be indexable. This is the SEO regression the PR is trying to prevent.

Also note: in Vercel's path-to-regexp, :path* already matches zero or more segments, so once the path is corrected the explicit /blog/tag rule becomes redundant with /blog/tag/:path*.

🛠️ Proposed fix
     {
-      "source": "/blog/tags",
-      "headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
-    },
-    {
-      "source": "/blog/tags/:path*",
+      "source": "/blog/tag/:path*",
       "headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
     },

If you'd rather keep both (in case tagsBasePath is changed later), add /blog/tags/:path* as a second rule instead of replacing — but the singular form is the one that actually matches today's routes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
"source": "/blog/tags",
"headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
},
{
"source": "/blog/tags/:path*",
"headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
},
{
"source": "/blog/tag/:path*",
"headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vercel.json` around lines 14 - 21, The vercel.json header rules use the wrong
path ("/blog/tags" and "/blog/tags/:path*") so they don't match the actual
Docusaurus output where tagsBasePath is set to 'tag'; update the rules to target
"/blog/tag/:path*" (or add "/blog/tags/:path*" as an additional rule if you want
both) and remove the redundant explicit "/blog/tag" entry since ":path*" already
covers the index.

Comment thread vercel.json
Comment on lines +34 to +37
{
"source": "/blog/page/:path*",
"headers": [{ "key": "X-Robots-Tag", "value": "noindex, follow" }]
},
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.

⚠️ Potential issue | 🟡 Minor

/blog/page/:path* is effectively dead given postsPerPage: "ALL".

The blog is configured with postsPerPage: "ALL" in docusaurus.config.js, so Docusaurus does not emit any /blog/page/N paginated list pages. This rule is harmless but inert. Safe to leave as a guard in case pagination is re-enabled later; just flagging so you know it's not currently doing anything.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vercel.json` around lines 34 - 37, The route entry "/blog/page/:path*" in
vercel.json is inert because Docusaurus is configured with postsPerPage: "ALL"
in docusaurus.config.js, so no paginated blog pages are emitted; either remove
the "/blog/page/:path*" rule to clean up the config or keep it intentionally as
a guard and add a concise comment explaining it is inactive while postsPerPage
is "ALL" so future maintainers understand why it exists.

@Jordy-Baby Jordy-Baby requested a review from nikbhintade April 29, 2026 14:09
Replaces @docusaurus/plugin-client-redirects (which emitted thin HTML
stubs with meta refresh) with server-side 301s in vercel.json. This
resolves Moz flags for missing H1, meta refresh, thin content, and
title issues on 12+ redirect URLs.

Adds 14 new redirect rules covering GSC 404s:
- /blog/blog/:path* wildcard for double-prefix external link errors
- Old /docs/HyperIndex/v2/* paths to current equivalents
- Wrong product combos (HyperSync/HyperIndex <-> HyperRPC overviews)
- Legacy docs paths (/docs/migration-guide, /docs/api, etc.)

Adds X-Robots-Tag noindex headers for:
- Blog archive/RSS/pagination/tags (low-value SEO, eat crawl budget)
- /docs/HyperIndex-LLM/*, /docs/HyperSync-LLM/*, /docs/HyperRPC-LLM/*
  (consolidated LLM-consumption pages that duplicate main docs content,
  resolving GSC "Duplicate, Google chose different canonical" flag)

Adds global noindex metadata to docusaurus.config.llm.js so the
separate llm-docs.envio.dev build emits noindex meta on every page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Jordy-Baby
Copy link
Copy Markdown
Collaborator Author

Closing — the underlying meta-refresh stubs are a Moz audit finding, not a search-ranking problem. Google handles meta-refresh as equivalent to 301 and indexes the canonical pages correctly. Reopen if Moz dashboard cleanliness becomes a priority.

@Jordy-Baby Jordy-Baby closed this Apr 29, 2026
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