This is an SEO post about an SEO mistake — which is the most embarrassing kind.
The trap
In the App Router, metadata cascades. If your root layout.tsx sets:
export const metadata = {
alternates: { canonical: "/" },
};…then every page that doesn't override it inherits canonical: "/". So your detail pages, your category pages, everything, quietly tells Google "the canonical version of me is the homepage." That's an instruction to treat all of them as duplicates of / — a fast path to getting the real content dropped from the index.
I had this on five apps before I noticed. The pages were fine; the canonical tag was throwing them away.
The fix
Canonical is per-page. Each route owns its own:
// in the page/route, not a blanket layout default
export const metadata = {
alternates: { canonical: absoluteUrl(thisPagePath) },
};Don't set a blanket canonical in the root layout. If you want a default, derive it from the current path, never hardcode /.
The honest part
Canonical is a footgun precisely because nothing breaks. The site builds, renders, and looks perfect; the only symptom is search traffic that never arrives, weeks later, for a reason you can't see in the browser. When I build anything now, per-page canonical is on the checklist next to "does it compile" — because "it renders" and "search can index it" are different claims, and only one of them shows up in dev.