Files
Pamela Chia a9078612f2 fix(www): stop cross-zone link prefetch (#51066)
About 95% of the 404s served on supabase.com are App Router RSC
prefetches (`?_rsc=`) that www `<Link>`s fire at paths another zone
serves: `/docs`, `/dashboard`, `/library`, and the footer's
`humans.txt`, `lawyers.txt` and `security.txt`. Next.js can't prefetch
or client-navigate across multi-zone boundaries, so each prefetch 404s
even though the link itself works. I turned every www link into another
zone into a plain `<a>` and added a lint rule so new ones stay that way.

**Changed:**
- **Cross-zone links are plain anchors**: links that always leave www
(literal `/docs`, `/dashboard` and `.txt` hrefs, absolute
`https://supabase.com/dashboard` URLs, the `getDashboardCtaHref` CTAs)
render `<a>`. Renderers whose href comes from data (nav, footer, plan
and add-on CTAs, product cards) branch on `isCrossZoneHref`, which reads
the zone list from `lib/rewrites.js`. In-zone links stay `<Link>` and
keep prefetching.
- **New literal links can't regress**: `www/no-cross-zone-link` errors
on a `next/link` `<Link>` whose literal or template href points at
another zone. It evaluates `lib/rewrites.js` as production, so `/docs`
counts in every environment.
- **Click tracking survives the full navigation**:
`sign_in_button_clicked`, `start_project_button_clicked` and
`www_pricing_plan_cta_clicked` now send with `keepalive`, like
`sign_in_submitted` already did, so an immediate page load can't cancel
them. The mobile nav Sign in and Start your project buttons used
`legacyBehavior`, which never called their `onClick`: PostHog has no
`Mobile Nav` location for either event in the last 30 days. Those clicks
report from this PR on.
- **Typecheck no longer crashes**: the functions page's default export
inferred a type through `RealtimeLogs`'s unexported `Props`, which makes
the native TypeScript compiler panic during `tsc --noEmit`. I exported
`Props`.

**Note:** the lint rule only sees literal hrefs. A new renderer whose
href comes from data needs its own `isCrossZoneHref` branch, and review
is the only check on that.

## To test
`/docs` is only rewritten on production and absolute
`https://supabase.com/...` links are cross-origin on a preview, so the
preview proves the relative non-docs cases (`/dashboard*`, `/library`,
the footer .txt files). `/docs/...` prefetches still appear on the
preview because it has no docs rewrite.

Tested on Vercel preview:
- [x] Open `/` with the network tab filtered to `_rsc` and scroll to the
footer: no requests for `/dashboard*`, `/library`, `/design-system`,
`/kb`, `/evals`, `/humans.txt`, `/lawyers.txt` or
`/.well-known/security.txt`, while in-zone ones such as `/pricing`,
`/features` and `/blog` still appear
- [x] Same check on `/pricing`, `/auth`, `/database`, `/storage`,
`/realtime`, `/edge-functions`, `/blog` and a blog post: no `_rsc`
requests to `/dashboard*`, `/library` or the footer .txt files
- [x] Open the Developers dropdown on desktop and the mobile menu at
390px: no new `_rsc` requests to `/dashboard*` or `/library`
- [x] Click header Docs, footer Humans.txt, the hero Start your project
button and the pricing Free plan button: each lands where it did before
(`/docs`, `/humans.txt` text, `https://supabase.com/dashboard/sign-up`,
`https://supabase.com/dashboard/new?plan=free`). Signed out, the Free
plan button lands on the dashboard sign-in with
`plan=free&returnTo=%2Fnew`
- [x] Click the hero Start your project button: the
`/platform/telemetry/event` POST with `start_project_button_clicked`
completes with a 2xx after the page starts navigating. 201 with the
navigation held; on the real navigation the event still reached staging
PostHog
- [x] At 390px, open the mobile menu and click Sign in: a
`/platform/telemetry/event` POST with `sign_in_button_clicked` and
`buttonLocation: "Mobile Nav"` fires. Start your project in the same
menu also sends `start_project_button_clicked` with `buttonLocation:
"Mobile Nav"`
- [ ] Signed in, load `/`: no `/dashboard/projects?_rsc=` request (not
run: the preview origin has no signed-in session)
- [x] Open the desktop Product dropdown and the Product section of the
390px mobile menu: Compute shows its Private Alpha badge and the other
products show none (checks the master merge into `MenuItem`)

After deploy, `/` and `/pricing` on supabase.com show no `_rsc` requests
to `/docs*`, `/dashboard*` or `/library`. After a full day, the share of
supabase.com 404s carrying `_rsc=` should drop from about 95% to under
10%, and `sign_in_button_clicked` and `start_project_button_clicked`
should start showing a `Mobile Nav` location in PostHog.

## Linear
- fixes GROWTH-1294
2026-10-05 15:17:04 -07:00
..
…
2026-10-02 19:35:56 +02:00
2026-07-01 12:59:00 +02:00
2026-01-12 10:19:08 -04:00
2026-07-23 11:16:39 +02:00
…