Skip to content
Documentation
Rule catalogue

hreflang.sitemap-mismatch

<head> alternates and sitemap locale coverage must agree

warningsite-wide

Why it matters

The head and the sitemap are two declarations of one intent, produced by different code paths, so they drift. Under-declaring hides real translations; over-declaring points hreflang at URLs the site itself does not list, which is read as a broken cluster.

What the finding looks like

The message goflag prints, with example values substituted.

warn hreflang.sitemap-mismatch Route /pricing: the sitemap lists es, pt-br but the <head> does not advertise them. Both are derived from the same intent and must not disagree.

Derive both from one locale-availability source

Written for the Next.js App Router. The finding is correct on any stack; only the remedy assumes one.

// Compute availability once, feed both the <head> and the sitemap.
const localesFor = (slug: string) =>
  allDocs.filter((d) => d.slug === slug && !d.draft).map((d) => d.locale);

// generateMetadata(): alternates.languages ← localesFor(slug)
// sitemap.ts:        alternates.languages ← localesFor(slug)

Says who?

This rule runs on the cross-page contract, which does not yet carry sources. It picks them up when the site-level rules move onto the same descriptor as the page rules.