Fix remaining broken docs redirect targets#7837
Fix remaining broken docs redirect targets#7837mhessdev wants to merge 1 commit intocodex/seo-docs-remediation-conceptsfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR updates documentation redirect management by adding audit coverage for hard-coded destinations in the script while systematically updating Vercel redirect configurations to consolidate routes—primarily migrating content to new "console" sections and remapping reference paths to more specific documentation destinations. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/docs/scripts/audit-redirects.mjs (1)
7-13: Optional follow-up:broadDestinationsis now stale relative to the new redirect targets.Not blocking this PR — the scope here is "ignore llms feeds" — but worth noting before it gets forgotten: this PR retargets a large chunk of
/docs/data-platform/**and/docs/platform/**onto/docs/console,/docs/console/concepts,/docs/console/more/support, and/docs/console/more/feature-maturity. None of those are inbroadDestinations, soshouldWarnForBroadRedirectfalls back to the depth heuristic (sourceDepth >= 4 && destinationDepth + 1 < sourceDepth). That heuristic misses cases like/docs/data-platform/projects(depth 3) →/docs/console/concepts(depth 3 after anchor strip), which arguably is a broad redirect and would have been caught if/docs/console/conceptswere in the set.Teaching the audit about the new common landing pages keeps the broad-redirect signal honest going forward.
♻️ Suggested expansion
const broadDestinations = new Set([ "/docs", "/docs/orm", "/docs/orm/reference/supported-databases", "/docs/orm/prisma-client/queries/crud", "/docs/orm/prisma-client/setup-and-configuration/introduction", + "/docs/console", + "/docs/console/concepts", + "/docs/console/more/support", + "/docs/console/more/feature-maturity", ]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/docs/scripts/audit-redirects.mjs` around lines 7 - 13, broadDestinations is stale and missing new common landing pages, causing shouldWarnForBroadRedirect to miss broad redirects; update the Set named broadDestinations to include the new targets (e.g., "/docs/console", "/docs/console/concepts", "/docs/console/more/support", "/docs/console/more/feature-maturity") so the heuristic correctly flags redirects to these landing pages; locate the constant broadDestinations in apps/docs/scripts/audit-redirects.mjs and add the new destination strings to the Set.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/docs/vercel.json`:
- Around line 2487-2587: The audit shows anchors in vercel.json redirects (e.g.,
destinations like /docs/orm/more/releases#roadmap and
/docs/accelerate/caching#stale-while-revalidate-swr, `#time-to-live-ttl`,
`#cache-strategies`) don't exist; fix by either adding explicit heading IDs in the
destination MDX files (e.g., add "## Roadmap {`#roadmap`}" or "{`#roadmap`}" on the
target page) or removing the anchor fragments from the redirect entries in
vercel.json, and update audit-redirects.mjs to stop stripping fragments and
instead parse target MDX/HTML to assert the anchor exists so future changes are
caught.
---
Nitpick comments:
In `@apps/docs/scripts/audit-redirects.mjs`:
- Around line 7-13: broadDestinations is stale and missing new common landing
pages, causing shouldWarnForBroadRedirect to miss broad redirects; update the
Set named broadDestinations to include the new targets (e.g., "/docs/console",
"/docs/console/concepts", "/docs/console/more/support",
"/docs/console/more/feature-maturity") so the heuristic correctly flags
redirects to these landing pages; locate the constant broadDestinations in
apps/docs/scripts/audit-redirects.mjs and add the new destination strings to the
Set.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9b28c372-10c5-4f37-9609-9a452e120cb3
📒 Files selected for processing (2)
apps/docs/scripts/audit-redirects.mjsapps/docs/vercel.json
| "destination": "/docs/console/getting-started#step-3-create-a-project", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/projects/edit-settings", | ||
| "destination": "/docs/data-platform/classic-projects/platform/projects/edit-settings", | ||
| "destination": "/docs/console/concepts#project", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/projects/delete-project", | ||
| "destination": "/docs/data-platform/classic-projects/platform/projects/delete-project", | ||
| "destination": "/docs/console/concepts#project", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/projects", | ||
| "destination": "/docs/data-platform/classic-projects/platform/projects", | ||
| "destination": "/docs/console/concepts#project", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments/view-all", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments/view-all", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments/create", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments/create", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments/edit-settings/edit-name-and-url-handle", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments/edit-settings/edit-name-and-url-handle", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments/edit-settings/change-default-environment", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments/edit-settings/change-default-environment", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments/edit-settings", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments/edit-settings", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments/delete", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments/delete", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/environments", | ||
| "destination": "/docs/data-platform/classic-projects/platform/environments", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/members/roles-permissions", | ||
| "destination": "/docs/data-platform/classic-projects/platform/members/roles-permissions", | ||
| "destination": "/docs/console/concepts#workspace", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/members/add", | ||
| "destination": "/docs/data-platform/classic-projects/platform/members/add", | ||
| "destination": "/docs/console/concepts#workspace", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/members/change-role", | ||
| "destination": "/docs/data-platform/classic-projects/platform/members/change-role", | ||
| "destination": "/docs/console/concepts#workspace", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/members/remove", | ||
| "destination": "/docs/data-platform/classic-projects/platform/members/remove", | ||
| "destination": "/docs/console/concepts#workspace", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/members", | ||
| "destination": "/docs/data-platform/classic-projects/platform/members", | ||
| "destination": "/docs/console/concepts#workspace", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/data-browser", | ||
| "destination": "/docs/data-platform/classic-projects/platform/data-browser", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/query-console", | ||
| "destination": "/docs/data-platform/classic-projects/platform/query-console", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/schema-viewer", | ||
| "destination": "/docs/data-platform/classic-projects/platform/schema-viewer", | ||
| "destination": "/docs/console/concepts#resources", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/account", | ||
| "destination": "/docs/data-platform/classic-projects/platform/account", | ||
| "destination": "/docs/console/concepts#user-account", | ||
| "permanent": true | ||
| }, | ||
| { | ||
| "source": "/docs/data-platform/github-integration", | ||
| "destination": "/docs/data-platform/classic-projects/platform/github-integration", | ||
| "destination": "/docs/console/concepts#resources", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify that anchor fragments used as redirect destinations resolve to actual headings
# on their destination MDX files. Reports any anchors that don't have a matching
# explicit `{`#anchor`}` or auto-slug-compatible heading.
set -euo pipefail
# Find all docs root candidates (handles content/docs and content/docs.v6)
docs_roots=$(fd -t d -d 3 '^docs(\.v6)?$' -- apps/docs/content 2>/dev/null || true)
if [ -z "$docs_roots" ]; then
echo "Could not locate docs content roots under apps/docs/content"
exit 0
fi
# Extract every anchored /docs destination from vercel.json
python3 - <<'PY'
import json, re, os, sys, pathlib
with open("apps/docs/vercel.json") as f:
cfg = json.load(f)
anchored = []
for r in cfg.get("redirects", []):
dest = r.get("destination", "")
if dest.startswith("/docs") and "#" in dest:
path, anchor = dest.split("#", 1)
anchored.append((r["source"], path.rstrip("/"), anchor))
# Build url -> mdx file map by reading frontmatter `url:` from every mdx
def slugify(text):
s = text.strip().lower()
s = re.sub(r"[`*_~]", "", s)
s = re.sub(r"[^\w\s-]", "", s)
s = re.sub(r"\s+", "-", s)
return s.strip("-")
url_to_file = {}
for root in ["apps/docs/content/docs", "apps/docs/content/docs.v6"]:
if not os.path.isdir(root):
continue
for p in pathlib.Path(root).rglob("*.mdx"):
raw = p.read_text(encoding="utf-8", errors="ignore")
if not raw.startswith("---\n"):
continue
end = raw.find("\n---\n", 4)
if end == -1:
continue
fm = raw[4:end]
m = re.search(r"^url:\s*(.+)$", fm, re.M)
if not m:
continue
url = m.group(1).strip().strip('"').strip("'")
full = ("/docs" + (url if url.startswith("/") else "/" + url)).rstrip("/")
url_to_file[full] = p
missing = []
for src, path, anchor in anchored:
f = url_to_file.get(path)
if not f:
# Audit handles this case; we only care about anchor resolution here.
continue
body = f.read_text(encoding="utf-8", errors="ignore")
# Look for explicit {`#id`}
explicit = set(re.findall(r"\{#([^}]+)\}", body))
# Auto-slugged headings
autos = set()
for m in re.finditer(r"^#{1,6}\s+(.+?)\s*$", body, re.M):
autos.add(slugify(m.group(1)))
if anchor not in explicit and anchor not in autos:
missing.append((src, path, anchor, str(f)))
if missing:
print(f"Anchors not found on destination page ({len(missing)} total):")
for src, path, anchor, f in missing:
print(f" {src} -> {path}#{anchor} (page: {f})")
else:
print("All anchored redirect destinations resolve to a real heading.")
PYRepository: prisma/web
Length of output: 838
Anchor validation gap is real — 5 broken anchors found in redirects.
Your observation about the audit script's blind spot is spot-on. audit-redirects.mjs strips anchors before validation, so it confirms the destination page exists but doesn't check that the anchor itself resolves to a heading. This is a footgun in a config with many anchored destinations.
A verification pass found 5 instances where anchors don't exist on their destination pages:
/docs/about/prisma/roadmapand/docs/more/roadmapboth point to/docs/orm/more/releases#roadmap— theroadmapanchor doesn't exist in that file./docs/data-platform/accelerate/conceptsredirects to/docs/accelerate/caching#stale-while-revalidate-swr— this anchor doesn't exist (also missing:#time-to-live-ttland#cache-strategies).
When users follow these redirects, they'll land silently at the top of the page instead of the intended section. Fix by either:
- Adding the missing anchor headings to the destination MDX files (e.g.,
## Roadmap {#roadmap}or explicit{#roadmap}), or - Removing the anchor fragments if the destinations changed during the consolidation.
Worth a scan through vercel.json to audit any other anchored destinations as well, in case more slipped through.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/docs/vercel.json` around lines 2487 - 2587, The audit shows anchors in
vercel.json redirects (e.g., destinations like /docs/orm/more/releases#roadmap
and /docs/accelerate/caching#stale-while-revalidate-swr, `#time-to-live-ttl`,
`#cache-strategies`) don't exist; fix by either adding explicit heading IDs in the
destination MDX files (e.g., add "## Roadmap {`#roadmap`}" or "{`#roadmap`}" on the
target page) or removing the anchor fragments from the redirect entries in
vercel.json, and update audit-redirects.mjs to stop stripping fragments and
instead parse target MDX/HTML to assert the anchor exists so future changes are
caught.
Summary
Verification
Summary by CodeRabbit