One line of Next.js metadata told Google not to index nine pages
I audited this site's SEO expecting to find thin content and weak titles. I found both. I also found that nine of eleven pages were explicitly asking Google not to index them.
<link rel="canonical" href="https://kazirahat.com/" />A canonical tag is not a hint about the current URL. It is a statement that this page duplicates another one and that the other one should be indexed instead. Every one of those pages was nominating the homepage in its place.
Where it came from
export const metadata: Metadata = {
metadataBase: new URL(siteUrl),
// ...
alternates: {
canonical: siteUrl, // <- inherited by every route
},
};Next.js merges root metadata into every route that does not override the same field. For title this is a feature — that is what title.template is for. For an absolute URL it is a site-wide claim, and it is silent: the build passes, the pages render, the tag looks plausible in view-source. Only two routes on the site were correct, and only because they happened to declare their own.
The fix
Delete it from the root, and give every route a self-referential canonical — including the homepage, which otherwise becomes the one page without one:
export const metadata: Metadata = {
title: "Next.js Performance & Design Systems",
description: "...",
alternates: { canonical: "/services" },
};Relative values resolve against metadataBase, and Next appends the trailing slash when trailingSlash: true is set, so /services correctly emits https://kazirahat.com/services/.
Check it in the built output, not the source
This class of bug is invisible in the source and obvious in the artifact. A static export makes that easy — walk the built directory, match each page's path against its own canonical, and assert zero mismatches:
for f in $(find out -name index.html); do
printf "%-34s " "$f"
grep -o '<link rel="canonical" href="[^"]*"' "$f"
doneSixteen of sixteen now point at themselves; before the fix, fourteen of sixteen pointed at the homepage. The same pass turned up a smaller version of the same mistake: the sitemap listed /about while trailingSlash: true makes the real URL /about/, so every entry in it was a redirect.
If you run a Next.js site and have never read the canonical tag out of your built HTML, go and read it now. It takes a minute, and the failure mode is that Google quietly agrees to ignore most of your site.