Let me see all the canonical URL references including the contact page:
Now I have the full picture. The fix requires removing trailing slashes from canonical URLs in app/layout.tsx, app/page.tsx, app/about/page.tsx, app/privacy-policy/page.tsx, and the sitemap entries. Let me read the page files to apply edits:
Now applying all edits in parallel:
All canonical URLs and OG url fields now match the no-trailing-slash convention used by the footer links, so crawlers won't see the /about/ → /about 301 chain anymore. Updated app/layout.tsx, app/page.tsx (canonical, og.url, schema.org WebSite/WebPage url and @id fields, plus SearchAction.target), app/about/page.tsx, app/privacy-policy/page.tsx, and the three app/sitemap.ts entries — keeping siteConfig.canonicalUrl (already slash-free) as the single source of truth. The sitemap now also advertises the canonical (no-slash) URLs, so Search Console will reindex without the redirect penalty.
Exactly — that's what I just shipped. Here's the recap of what was removed:
| File | Field | Before | After |
|---|---|---|---|
app/layout.tsx | metadata.alternates.canonical | https://mooseknuckle.it/ | https://mooseknuckle.it |
app/layout.tsx | metadata.openGraph.url | https://mooseknuckle.it/ | https://mooseknuckle.it |
app/page.tsx | canonical, og.url, schema.org WebSite/WebPage @id & url, SearchAction.target | …/ | … (no slash) |
app/about/page.tsx | canonical, og.url | /about/ | /about |
app/privacy-policy/page.tsx | canonical, og.url | /privacy-policy/ | /privacy-policy |
app/sitemap.ts | all three internal URLs (/about/, /contact/, /privacy-policy/) | trailing-slash | no-slash |
Footer links already point to the no-slash versions, so once this deploys the crawler will see a single canonical URL with no 301 hop. No change needed in next.config.mjs — Next.js's default trailingSlash: false was already aligned, the canonicals were just out of sync.