← Journal
SEO··4 min read·By North Foundry

The canonical tag mistake that hides a Next.js site

A canonical tag tells search engines which URL is the main version of a page. Set correctly, it prevents duplicate-content problems. Set wrongly, it tells Google to ignore the page it is on.

We found the wrong kind on our own site in October 2026. Every page, case studies and journal posts included, carried a canonical tag pointing at the homepage. This post explains how it happened, because the mistake is easy to make in the Next.js App Router and hard to notice.

What does a canonical tag do?

It is one line in the page's <head>:

<link rel="canonical" href="https://example.com/services/web-design" />

It says: "If you find this content at several URLs, treat this one as the original." Each page should normally point to itself.

What was the bug?

In the App Router, metadata defined in a layout is inherited by every page under it. Our root layout contained this:

// app/layout.tsx
export const metadata = {
  metadataBase: new URL("https://northfoundry.co"),
  alternates: { canonical: "https://northfoundry.co" },
};

It looks reasonable. It reads like "the canonical domain is this." What it actually does is put the homepage URL into the canonical tag of every route that does not set its own. None of ours did.

So /work, /journal/any-post and every other page said to Google: "I am a copy of the homepage. Index that instead."

Google treats a canonical tag as a strong hint, not a command, and it sometimes ignores one that is obviously wrong. Hoping it will is not a plan.

Why is it hard to notice?

  • The site looks perfect. Nothing is visibly broken.
  • The build passes, and so does the linter.
  • Each page has a unique title and description, so a quick check of the browser tab looks fine.
  • The homepage itself is correct.

The only symptom is slow: inner pages do not get indexed, or drop out. In Search Console they tend to appear under "Alternate page with proper canonical tag."

How do you check your own site?

Open any page that is not the homepage, view the page source, and search for canonical. The URL in that tag should be the URL of the page you are on.

From a terminal:

curl -s https://yoursite.com/some/page | grep -o '<link rel="canonical"[^>]*>'

If it prints the homepage on an inner page, you have this bug.

What is the fix?

Remove the canonical from the root layout, and set it on each page. For static pages:

// app/services/page.tsx
export const metadata = {
  title: "Services",
  alternates: { canonical: "/services" },
};

For dynamic routes, set it in generateMetadata:

export async function generateMetadata({ params }) {
  const { slug } = await params;
  return {
    title: post.title,
    alternates: { canonical: `/journal/${slug}` },
  };
}

Relative paths work because metadataBase in the layout supplies the domain.

We went one step further and wrapped this in a small helper that every page calls with its own path. It returns the canonical, Open Graph and Twitter tags together, which means a page cannot be added without them.

The same trap catches Open Graph tags

Next.js does not merge nested metadata objects. If a layout sets openGraph with an image and a page sets openGraph with only a title, the page's version replaces the layout's entirely. The image, URL and site name disappear. Our case study pages were being shared with no preview image for this reason.

The rule that covers both: in the root layout, set only what is true for every page. Anything that names a specific URL belongs on the page.

What should you do after fixing it?

  1. Deploy, then check three or four inner pages by hand.
  2. Resubmit the sitemap in Google Search Console.
  3. Use URL Inspection on your most important pages and request indexing.
  4. Give it a few weeks. Recrawling is not instant.

The wider lesson

Technical SEO problems are usually code problems. No amount of content will rank a page that tells search engines to ignore it. If you would like someone to look for this kind of thing in your codebase, it is what our technical SEO and GEO service is for. For what to do once the foundations are right, read what is generative engine optimization.

Related service

SEO & GEO

Fixed in the codebase, not filed in a PDF. Built to be ranked by Google and quoted by AI.

Building something this applies to?

Book a discovery call→