Shipping & Infra2 min read

The one Next.js config line that almost deindexed 5 of my apps

A canonical URL of '/' set in the root layout is inherited by every page — so every page tells Google it's a duplicate of the homepage. Here's the trap and the fix.

#nextjs#seo#canonical#metadata
Concept diagram: Next.js canonical inheritance
A concept diagram summarizing the post.

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.

YouTube

One line of code almost deindexed 5 of my apps

Related