Skip to content

fix(seo): restore redirects for deleted v6 docs and repair metadata regressions - #8144

Merged
ankur-arch merged 6 commits into
mainfrom
seo/traffic-investigation-fixes
Aug 26, 2026
Merged

fix(seo): restore redirects for deleted v6 docs and repair metadata regressions#8144
ankur-arch merged 6 commits into
mainfrom
seo/traffic-investigation-fixes

Conversation

@ankur-arch

@ankur-arch ankur-arch commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

While investigating the reported traffic decline, we found five concrete technical SEO problems across the docs, blog, and main site. This PR fixes those problems.

The analytics context in brief: the decline shown in PostHog is larger than the real decline. PostHog became consent-gated on June 22 (#7971), so it now only counts visitors who accept analytics cookies.

Search Console, which is not affected by cookie consent, still shows a real organic decline. But rankings have broadly remained stable or improved. The remaining decline appears to come mostly from fewer search impressions and fewer clicks per impression.

This PR addresses the technical issues discovered during the investigation. It does not attempt to solve changes in search demand or search-result click behavior.

What this PR changes

1. Redirect deleted Prisma v6 documentation URLs

Problem

The May 5 v6 consolidation (#7864) removed several v6 URL trees: guides, Prisma Postgres, Accelerate, Platform, AI, and the quickstarts. Redirects were only created for the ORM section. The other URLs have returned 404 since.

Why it matters

Search Console showed these URLs still receiving roughly 600 clicks per month in March. By August Google had dropped nearly all of them from results (3 v6 URLs left, 0 clicks), so the redirects mostly recover inbound link value and stop the remaining impressions from landing on a 404, rather than recovering traffic.

Change

Add 125 redirects to apps/docs/vercel.json. Each old URL maps to its exact replacement page where one exists, otherwise to the closest relevant section.

Verification

apps/docs/scripts/audit-redirects.mjs passes: 1,427 redirect rules checked against 686 live documentation routes, no broken destinations, no redirect loops, no chains returning to /docs/v6. The v6 rules were re-checked after merging the Prisma 8 docs tree from main.

2. Move robots rules to the robots.txt crawlers actually read

Problem

Docs and blog are separate Next.js apps served under www.prisma.io through path prefixes (basePath). Each defines its own robots.ts, but because of the prefix those files are served at /docs/robots.txt and /blog/robots.txt. Crawlers only request /robots.txt at the root, which is served by apps/site. So the rules defined in docs and blog have never affected crawlers in production.

Why it matters

Those rules block crawling of URLs that should not be indexed: OG image endpoints, API routes, and parameterized listing URLs such as /blog?page=2.

Change

Port the rules into apps/site/src/app/robots.ts, the file behind the real /robots.txt. The ?tag= rule is intentionally not ported: blog tag pages currently redirect into /blog?tag= URLs, and blocking those would block a redirect destination. The right crawl behavior for tag URLs remains a follow-up.

Verification

The rule list is carried over unchanged apart from the ?tag= exclusion. Only the serving location changes.

3. Prevent the internal origin hosts from being indexed

Problem

The multi-zone setup uses docs.prisma.io and blog.prisma.io internally as origins behind www.prisma.io. Those hosts can also be requested directly, and they serve full copies of the same content. Neither serves a robots.txt today (both return 404 in production). Search Console shows some blog.prisma.io URLs indexed, including ?tag= and ?page= variants, with impressions and zero clicks.

Why it matters

Duplicate copies of pages compete with the canonical www.prisma.io versions in search results.

Change

Serve a robots.txt on each origin host that disallows all crawling:

  • apps/docs/src/app/robots-origin.txt/route.ts
  • apps/blog/src/app/robots-origin.txt/route.ts

Each app redirects /robots.txt to its route using a basePath: false redirect. That option matches the URL without the app's path prefix, so the redirect answers at docs.prisma.io/robots.txt rather than docs.prisma.io/docs/robots.txt. Google follows robots.txt redirects and treats the target as the host's robots file.

A redirect is used rather than a rewrite because Next.js only allows basePath: false rewrites for external destinations. The first version of this change used a rewrite and failed the docs and blog builds; the redirect form is the same mechanism both apps already use for their root redirects.

Requests that come through www.prisma.io are unaffected: www serves its own /robots.txt from apps/site, and the zone routing only forwards /docs/* and /blog/* paths to the origin apps. Redirecting the whole origin hosts to www would be the stronger fix, but the zone routing itself sends requests to those hosts, so that is not an option.

Verification

Confirmed both origin hosts return 404 for /robots.txt in production today. Verified in a local dev server that /robots.txt returns a 307 to the robots route and the target serves the disallow-all body.

4. Fix markdown versions of blog posts on www

Problem

Pages are also exposed as markdown (.md and .mdx suffixes) for AI agents and other machine consumers, and the docs HTTP headers advertise this. For blog posts this only works on the internal origin host. In production, blog.prisma.io/blog/<post>.mdx returns 200 while www.prisma.io/blog/<post>.mdx returns 404.

The cause is rewrite ordering in apps/site/next.config.mjs. Rewrites run in order, and the site's generic /:path*.mdx rule matches /blog/*.mdx before the rule that forwards blog paths to the blog app. The generic rule sends the request to the site's own llms.mdx handler, which is a stub that always returns 404.

Change

In apps/site/next.config.mjs, add forwarding rules for /blog/*.mdx and /blog/*.md ahead of the generic rule, following the same pattern as the existing docs forwarding rule next to them. Also add .md handling to the blog app so both suffixes work, matching docs.

Verification

Production probes documented the broken behavior (200 on the origin host, 404 on www for the same post). node --check passes on the modified config.

5. Restore canonical URLs on the main site

Problem

A canonical URL tells search engines which URL is the authoritative version of a page. The rebrand (#8142) rewrote every static site page with a bare metadata object instead of createPageMetadata(), so since it shipped no www.prisma.io page has emitted a <link rel="canonical">. Confirmed in production: /, /orm, /compute, /pricing, /postgres and /stack all render without one, while docs pages still do. The original version of this PR only fixed /compute, which at the time was the single page missing it.

Change

Add alternates.canonical to the 34 site pages that bypass createPageMetadata() and a metadata export on the homepage. Paths are relative and resolve against the root layout's metadataBase, so they follow getBaseUrl() like the rest of the site.

6. Redirect pages the rebrand removed

Problem

#8142 also deleted /docs/postgres/database/local-development and /docs/postgres/database/direct-connections without redirects. The local development page is the single largest live 404 on the site: about 135 search clicks and 50,000 impressions in the last 28 days, and it is linked from five release posts on the blog. PostHog's 404 pageviews for the last 28 days also surface /docs/v7, the legacy /docs/getting-started/prisma-orm/* tree (linked from older blog posts), and a lowercased copy of a blog slug.

Change

Redirect both Prisma Postgres pages to their replacements (/docs/local-development/postgres and /docs/postgres/database/connecting-to-your-database) and repoint the v6 rules at the same targets. Add /docs/v7 to /docs/orm/v7, a prefix rule for the legacy getting-started tree, and the lowercased blog slug.

7. Fix remaining metadata regressions

Three small, independent fixes:

  • Blog structured data logo. Every BlogPosting referenced /logo.png, which does not exist. It now uses /images/logo.svg, the asset the Organization schema already uses.
  • Missing series redirect. Rename series slug from agentic-software-development to agentic-engineering #7972 renamed the blog series slug agentic-software-development to agentic-engineering without a redirect, so the old URL returned 404. Added the redirect.
  • Production base URL guard. Docs and blog build canonical URLs, sitemap URLs, and JSON-LD IDs from getBaseUrl(). If NEXT_PUBLIC_PRISMA_URL were ever unset in production, they would fall back to the Vercel deployment hostname and stamp the wrong host into that metadata. They now fall back to https://www.prisma.io in production, matching apps/site. This is a defensive guard. There is no evidence that wrong hosts are currently being generated.

Traffic investigation: what we actually know

The short answer to "is traffic really down from 350k to 90k": no. The 350k and 90k numbers come from two different measurement regimes, so they are not comparable. Roughly, real traffic went from about 380k monthly visitors in March to an estimated 210k in July. That is still a real decline, and Search Console confirms it, but it is about half the size the dashboard suggests.

The June drop in PostHog is a tracking change (confirmed)

Since June 22 (#7971), PostHog only loads after a visitor accepts analytics cookies through CookieYes. Visitors who do not consent are no longer counted.

Every signal that cookie consent cannot affect stayed roughly flat across that date. Comparing the six weekdays before and after the change (June 16 to 21 vs June 23 to 28):

Signal Affected by consent gating? Change
PostHog visitors, www.prisma.io Yes -53%
Google Search Console clicks No -9%
PostHog visitors, console.prisma.io No -8%
Signups (console:user_signed_up) No -16%*

* The before-window includes a June 17 signup spike; the weekly signup rate stays in its normal range before and after.

Only the consent-gated metric dropped sharply. The drop also happened simultaneously across every acquisition channel including direct visits, which no search or ranking change can produce. Based on the difference between PostHog and Search Console trends, the dashboard overstates the decline by roughly 2.5x.

Search traffic is genuinely down

Search Console is unaffected by cookie consent. Comparing March 1 to 28 with July 29 to August 25:

  • Clicks: 181,698 to 94,159 (-48%)
  • Impressions: 6.75M to 4.26M (-37%)
  • Desktop average position: 7.7 to 10.5 (worse); mobile 9.7 to 7.3 (better)

Through July the picture was fewer clicks at stable rankings. The August data adds a rankings component on desktop, which is where 90% of clicks come from. That overlaps with the Prisma 8 docs cutover and the rebrand (both mid-August), and two of the defects this PR fixes (site pages without canonicals, a high-traffic docs page 404ing) date from the same change. Search Console alone cannot separate the two, so this PR fixes the defects and leaves the attribution open.

What appears to be driving it

Fewer clicks for the same visibility. /docs/orm/prisma-migrate/getting-started held position 4.6 with slightly higher impressions, yet clicks fell 69% (CTR 2.1% to 0.6%). The page kept appearing in roughly the same place in Google, but fewer people clicked it. The timing overlaps with Google's May 21 to June 2 core update and broader AI Overview expansion, but Search Console alone cannot establish the cause.

Fewer searches for Prisma terms. Queries such as "prisma", "prisma seed", and "prisma migrate" received 30 to 58% fewer impressions while Prisma continued to rank near the top for them. Fewer searches are happening for those terms, rather than Prisma ranking lower. Developers shifting from search to AI assistants and summer seasonality (2025 shows a similar March-to-summer dip) are plausible contributing factors, not established causes.

Validation

Investigation

  • Search Console API data reviewed from January through August 25
  • Compared clicks, impressions, CTR, and average position by date
  • Compared periods by page, query, and device
  • Inspected v6 URLs and origin-host URLs separately
  • Probed the HTTP status of the top 600 www pages by search clicks: 397 serve 200, 202 redirect (Prisma 8 tree moves), 1 returns 404 (fixed here)
  • Cross-checked PostHog 404 pageviews on www for the last 28 days against production

Code

  • Redirect audit passes across 1,427 rules and 686 live docs routes
  • No broken redirect destinations, loops, or chains returning to /docs/v6
  • node --check passes for all modified next.config.mjs files
  • Production probes reproduce the documented 200/404 behavior
  • Typechecking passes for touched applications, except for pre-existing errors in unrelated files
  • Branch is merged with main as of 2026-08-26, including the Prisma 8 docs cutover and the rebrand

Out of scope

Known issues found during the investigation, intentionally not included in this PR:

  • Blog has llms-full.txt but no llms.txt index
  • The main site's llms.mdx route is still a stub, so site pages have no markdown versions
  • Desired crawl behavior for blog ?tag= URLs needs a product/SEO decision
  • The redirect audit is not yet part of CI
  • Roughly 20 further legacy docs URLs (2021-era paths, Pulse, Data Proxy) still show up as 404s in PostHog at 5 to 15 visits a month each; not worth individual rules
  • /docs/guides/upgrade-prisma-orm/v8 gets a steady trickle of visits but no such guide exists yet

Summary by CodeRabbit

  • New Features
    • Added redirects for legacy documentation and blog URLs.
    • Added Markdown and MDX content renditions for blog pages.
    • Added dedicated robots.txt policies for blog and documentation sites.
  • SEO
    • Added canonical URLs across site pages, including Compute and key product, legal, and program pages.
    • Expanded crawler exclusions for selected documentation, blog, API, and query-parameter URLs.
    • Improved production URL fallbacks and corrected the structured-data publisher logo.

…egressions

The May 5 v6 docs consolidation (309fe27) deleted ~150 indexed
/docs/v6/** pages but only added redirects for the ORM section, leaving
the rest 404ing during a period of declining search traffic. Add 125
redirect rules mapping every deleted v6 URL to its current equivalent
(exact page where one exists, section index otherwise), verified with
scripts/audit-redirects.mjs against the live route set.

Also fix three smaller regressions found in the same investigation:

- /compute shipped without a canonical URL (only page not using
  createPageMetadata)
- every BlogPosting emitted a publisher logo pointing at the
  nonexistent /logo.png; use /images/logo.svg like the site
  Organization schema
- the agentic-software-development series rename shipped without a
  redirect, 404ing the old sitemap-listed URL

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview Aug 26, 2026 9:02am
docs Ready Ready Preview Aug 26, 2026 9:02am
eclipse Ready Ready Preview Aug 26, 2026 9:02am
site Ready Ready Preview Aug 26, 2026 9:02am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 849c14cd-fe1c-46fc-bc6d-97bbc2e4ee10

📥 Commits

Reviewing files that changed from the base of the PR and between c4e0fe1 and 1033395.

📒 Files selected for processing (46)
  • ARCHITECTURE.md
  • apps/blog/next.config.mjs
  • apps/blog/src/app/(blog)/[slug]/page.tsx
  • apps/blog/src/app/robots-origin.txt/route.ts
  • apps/blog/src/lib/url.ts
  • apps/docs/next.config.mjs
  • apps/docs/src/app/robots-origin.txt/route.ts
  • apps/docs/src/lib/urls.ts
  • apps/docs/vercel.json
  • apps/site/next.config.mjs
  • apps/site/src/app/brand-kit/page.tsx
  • apps/site/src/app/brand/comparison/page.tsx
  • apps/site/src/app/brand/prisms/page.tsx
  • apps/site/src/app/brand/rays/page.tsx
  • apps/site/src/app/changelog/page.tsx
  • apps/site/src/app/community/page.tsx
  • apps/site/src/app/company/careers/page.tsx
  • apps/site/src/app/company/page.tsx
  • apps/site/src/app/compute/page.tsx
  • apps/site/src/app/contact/page.tsx
  • apps/site/src/app/customers/page.tsx
  • apps/site/src/app/demo/calculator-options/page.tsx
  • apps/site/src/app/demo/page.tsx
  • apps/site/src/app/demo/thank-you/page.tsx
  • apps/site/src/app/enterprise/page.tsx
  • apps/site/src/app/event-code-of-conduct/page.tsx
  • apps/site/src/app/legal/privacy/page.tsx
  • apps/site/src/app/legal/security-and-compliance/page.tsx
  • apps/site/src/app/legal/sla/page.tsx
  • apps/site/src/app/legal/terms/page.tsx
  • apps/site/src/app/newsletter/page.tsx
  • apps/site/src/app/newsletter/unsubscribe/page.tsx
  • apps/site/src/app/orm/page.tsx
  • apps/site/src/app/page.tsx
  • apps/site/src/app/postgres/page.tsx
  • apps/site/src/app/pricing/page.tsx
  • apps/site/src/app/programs/oss-friends/page.tsx
  • apps/site/src/app/programs/page.tsx
  • apps/site/src/app/programs/partners/page.tsx
  • apps/site/src/app/programs/startups/page.tsx
  • apps/site/src/app/query-insights/page.tsx
  • apps/site/src/app/robots.ts
  • apps/site/src/app/stack/page.tsx
  • apps/site/src/app/studio/page.tsx
  • apps/site/src/app/support-policy/page.tsx
  • apps/site/src/app/support/page.tsx
🚧 Files skipped from review as they are similar to previous changes (11)
  • apps/blog/src/app/(blog)/[slug]/page.tsx
  • apps/docs/src/app/robots-origin.txt/route.ts
  • apps/site/src/app/compute/page.tsx
  • apps/blog/src/app/robots-origin.txt/route.ts
  • apps/docs/src/lib/urls.ts
  • apps/docs/next.config.mjs
  • apps/site/src/app/robots.ts
  • apps/blog/next.config.mjs
  • ARCHITECTURE.md
  • apps/site/next.config.mjs
  • apps/blog/src/lib/url.ts

Included review availability: 4 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


Walkthrough

The pull request updates production URL fallbacks, canonical metadata, redirects, Markdown rewrites, and robots routes across the blog, docs, and site applications.

Changes

Cross-app routing and metadata

Layer / File(s) Summary
Canonical URL and metadata updates
ARCHITECTURE.md, apps/blog/src/lib/url.ts, apps/docs/src/lib/urls.ts, apps/site/src/app/*/page.tsx, apps/blog/src/app/(blog)/[slug]/page.tsx
Production URL fallbacks use https://www.prisma.io. Site pages declare canonical URLs. Blog JSON-LD uses the SVG logo path.
Blog redirects and Markdown routes
apps/blog/next.config.mjs, apps/blog/src/app/robots-origin.txt/route.ts
The blog adds robots, slug, and series redirects. It also rewrites .md paths and serves a static origin robots route.
Documentation redirects and robots route
apps/docs/next.config.mjs, apps/docs/src/app/robots-origin.txt/route.ts, apps/docs/vercel.json
The docs application adds an origin robots route and permanent redirects for legacy versioned paths.
Site zone rewrites and crawl rules
apps/site/next.config.mjs, apps/site/src/app/robots.ts
The site forwards blog Markdown renditions to BLOG_ORIGIN and adds docs and blog exclusions to its robots response.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 10333

The PR restores redirects and metadata behavior across the site, docs, and blog, with no actionable merge-blocking risk remaining beyond normal checks and review.

Suggested reviewers: nurul3101

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 44 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary SEO changes: restoring redirects for deleted v6 documentation and fixing metadata regressions. It is concise and specific, although it does not mention the rob…
Full details: Docstring Coverage

Explanation

Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 44 files. (2 skipped: 2 unsupported.)

Full details: Title check

Explanation

The title clearly identifies the primary SEO changes: restoring redirects for deleted v6 documentation and fixing metadata regressions. It is concise and specific, although it does not mention the robots.txt and blog forwarding changes, which are secondary objectives.

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch seo/traffic-investigation-fixes

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

@argos-ci

argos-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Awaiting the start of a new Argos build…

…estore blog markdown renditions

Follow-ups from validating the traffic investigation against Search
Console.

The docs and blog robots.ts files render under each zone's basePath, so
their Disallow rules never reached the live www.prisma.io/robots.txt.
Port the parameter and og/api rules into the site robots.ts, which is
the only robots.txt crawlers see. The ?tag= rule is deliberately not
ported because blog tag pages 301 into /blog?tag= URLs.

Search Console shows blog.prisma.io origin-host URLs (including
?tag=/?page= variants) indexed with impressions and zero clicks, and
neither origin host serves a robots.txt at all. Add a disallow-all
robots.txt on docs.prisma.io and blog.prisma.io via basePath-free
rewrites; www traffic never reaches these routes.

Blog markdown renditions 404 on www because the site's bare /:path*.mdx
rewrite captures /blog/*.mdx before the blog zone forward and lands in
the site's stub llms.mdx route (verified in production). Forward
/blog/*.mdx and /blog/*.md to the blog zone, and teach the blog app the
.md suffix that docs already advertises in its Link headers.

Also add the production-host guard to docs and blog getBaseUrl() so
canonicals, sitemaps, and JSON-LD ids can never fall back to a Vercel
deployment hostname, matching apps/site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Next.js only allows basePath:false rewrites for external destinations,
so the previous rewrite failed the docs and blog builds with "Invalid
rewrite found". Use a basePath:false redirect instead, which both
configs already rely on for their root redirects. Google follows
robots.txt redirects and treats the target as the host's robots file.

Verified in dev: /robots.txt returns 307 to /docs/robots-origin.txt and
the target serves the disallow-all body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 12, 2026
…oved by the rebrand

The rebrand (#8142) rewrote every static site page with a bare metadata
object, so no www.prisma.io page (including the homepage) has emitted a
canonical link since it shipped. Add alternates.canonical to all 34 pages
that bypass createPageMetadata, plus a metadata export on the homepage.

The rebrand also removed /docs/postgres/database/local-development, which
still receives ~135 search clicks and 50k impressions a month, and
direct-connections, both linked from several release posts. Redirect them
to their replacement pages and repoint the v6 rules at the same targets.
Also cover /docs/v7, the legacy /docs/getting-started/prisma-orm tree, and
a lowercased blog slug, all of which show up as 404 pageviews in PostHog.
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@ankur-arch
ankur-arch merged commit 2f89ccb into main Aug 26, 2026
16 checks passed
@ankur-arch
ankur-arch deleted the seo/traffic-investigation-fixes branch August 26, 2026 09:10
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