From a186f9e91e9594e253c569cc71c61d110ad3ab9d Mon Sep 17 00:00:00 2001
From: Marc LeBlanc <7050295+marcleblanc2@users.noreply.github.com>
Date: Thu, 17 Sep 2026 04:30:43 -0600
Subject: [PATCH] fix/seo: Emit a per-page canonical URL
Every docs page shipped ,
so search engines treat all 500+ pages as duplicates of the landing page.
generateMetadata now sets alternates.canonical to the page's own path;
metadataBase in layout.tsx resolves it to an absolute URL.
Found by the docs site audit in
https://ampcode.com/threads/T-01a0ae50-f7f0-779c-aa66-3887c9953e33
Amp-Thread-ID: https://ampcode.com/threads/T-01a0aed2-5fbe-7768-85ea-1378bf98f9ff
Co-authored-by: Amp
---
src/app/[...slug]/page.tsx | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/app/[...slug]/page.tsx b/src/app/[...slug]/page.tsx
index 01681c596..3bc78c815 100644
--- a/src/app/[...slug]/page.tsx
+++ b/src/app/[...slug]/page.tsx
@@ -31,6 +31,10 @@ export const generateMetadata = async ({params}: Props) => {
const ogImageUrl = `${process.env.NEXT_PUBLIC_DOCS_BASE_PATH || ''}/api/og/${path}`;
return {
title,
+ // The root layout's canonical is the landing page; without this
+ // override every docs page tells search engines it is a duplicate
+ // of https://sourcegraph.com/docs.
+ alternates: {canonical: `/docs${post.url}`},
openGraph: {
images: [{url: ogImageUrl, width: 1200, height: 630}]
},