Skip to content

[finding] docs site: apps/docs/app/page.tsx is a shadowed route — the proxy rewrites / to /en, so it never runs #12255

Description

@os-zhuang

One-liner

apps/docs/app/page.tsx is a shadowed route. It redirects to /docs, but the runtime
never runs it: proxy.ts rewrites / to /en, so the homepage is always served by
app/[lang]/page.tsx. grep finds a root page that says "the root redirects to the
docs"; the site does not do that.

Observation class (dead code), not a user-visible bug. Filed unassigned for triage.

Measured — 2026-08-25, production build of apps/docs served with next start

$ curl -s -o /dev/null -w "%{http_code} %{content_type}\n" http://localhost:38413/
200 text/html; charset=utf-8

A 200 with the homepage. If app/page.tsx ran, this would be a 307 to /docs.

Both routes are built — the route table from the same next build lists them side by
side:

┌ ○ /
├ /[lang]
│ └ ● /en

Mechanism: proxy.ts's matcher is
'/((?!api|_next/static|_next/image|favicon.ico|.*\\..*).*)'. For / the capture group
is the empty string, the dotted-path lookahead does not fire, so the proxy matches and
rewrites / to /enapp/[lang]/page.tsx, the real homepage. Nothing reaches
app/page.tsx.

Why it is worth recording

AGENTS.md "Route & surface ownership" rule 1 names exactly this shape: a shadowed
duplicate is "code that grep finds and the runtime never runs — the exact input that
makes an agent (or a human) reason confidently from dead code".

Concretely: the docs-site indexability epic #12243 has cards that add metadataBase,
canonical links and JSON-LD to the homepage (#12234, #12240). An agent that puts the
homepage's canonical link in app/page.tsx will ship a green PR that changes nothing
served.

Options for whoever picks this up

  1. Delete app/page.tsx — the proxy owns /. Simplest, and makes the ownership
    obvious. Check first that Next still builds with no root page.tsx (there is a
    root app/layout.tsx).
  2. Keep it and say so — if it is a deliberate no-proxy fallback (a deployment where
    middleware does not run), the file should carry a comment saying that, since its
    current comment ("Middleware should handle locale routing") reads as if the file were
    live.

Either way the fix is one file. Do not change the proxy matcher as part of this — that
matcher is load-bearing for #12233 and belongs to that card.

Source

Noticed while implementing #12232 (robots.txt / sitemap.xml) against apps/docs;
outside that card's file surface, so recorded rather than fixed.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions