From 920fe5b629c336cbc7898776c3ba8105cf00dfc1 Mon Sep 17 00:00:00 2001 From: winter100004 Date: Mon, 15 Jun 2026 14:26:43 +0800 Subject: [PATCH] chore(seo): add sitemaps and per-page canonical to docs and site MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Google Search Console reported "Page with redirect" and "Alternate page with proper canonical tag" — both benign (intentional .html→clean and www→apex redirects, and correctly-honored canonicals). The actionable gap was no sitemap on either site (sitemap.xml was 404), so Google relied on crawling URL variants rather than the canonical URLs. - docs (VitePress): emit a sitemap (hostname docs.openpicker.dev) and add a self-referential canonical per page via transformPageData. With cleanUrls the canonical/sitemap entries are the clean URLs, so .html variants and the production *.workers.dev origin consolidate to them. - site: add a static public/sitemap.xml listing https://openpicker.dev/ (the marketing site is a single page; it already sets a self canonical). Submit each sitemap in the corresponding Search Console property. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/docs/.vitepress/config.ts | 15 +++++++++++++++ apps/site/public/sitemap.xml | 6 ++++++ 2 files changed, 21 insertions(+) create mode 100644 apps/site/public/sitemap.xml diff --git a/apps/docs/.vitepress/config.ts b/apps/docs/.vitepress/config.ts index cf8cd26..329e6c6 100644 --- a/apps/docs/.vitepress/config.ts +++ b/apps/docs/.vitepress/config.ts @@ -9,6 +9,21 @@ export default defineConfig({ cleanUrls: true, lastUpdated: true, srcExclude: ["**/README.md"], + // Emit a sitemap so Google indexes the canonical (clean) URLs directly instead of + // discovering URL variants and consolidating them. Submit it in Search Console. + sitemap: { + hostname: "https://docs.openpicker.dev", + }, + // Self-referential canonical per page. With cleanUrls, duplicate variants Google may + // crawl (…/page.html → 307 → /page, the production *.workers.dev origin, etc.) all + // point back to the clean URL, so they consolidate here rather than competing. + transformPageData(pageData) { + const canonical = `https://docs.openpicker.dev/${pageData.relativePath}` + .replace(/index\.md$/, "") + .replace(/\.md$/, "") + pageData.frontmatter.head ??= [] + pageData.frontmatter.head.push(["link", { rel: "canonical", href: canonical }]) + }, head: [ ["link", { rel: "icon", href: "/openpicker.svg" }], ["meta", { name: "theme-color", content: "#0f172a" }], diff --git a/apps/site/public/sitemap.xml b/apps/site/public/sitemap.xml new file mode 100644 index 0000000..16b9761 --- /dev/null +++ b/apps/site/public/sitemap.xml @@ -0,0 +1,6 @@ + + + + https://openpicker.dev/ + +