Skip to content

Commit 8d96056

Browse files
committed
fix(sitemap): publish sitemap.xml alias alongside sitemap index
1 parent 2815771 commit 8d96056

4 files changed

Lines changed: 43 additions & 6 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"dev": "astro dev",
99
"prebuild": "node scripts/copy-post-assets.mjs",
1010
"build": "astro build",
11-
"postbuild": "pagefind --site dist",
11+
"postbuild": "node scripts/postbuild-sitemap-alias.mjs && pagefind --site dist",
1212
"preview": "astro preview",
1313
"perf:baseline": "node scripts/perf/lighthouse-baseline.mjs"
1414
},
@@ -30,4 +30,4 @@
3030
"sharp": "^0.34.5",
3131
"typescript": "^5.9.3"
3232
}
33-
}
33+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import fs from "node:fs";
2+
import path from "node:path";
3+
4+
const distDir = path.join(process.cwd(), "dist");
5+
const sitemapIndexPath = path.join(distDir, "sitemap-index.xml");
6+
const sitemapAliasPath = path.join(distDir, "sitemap.xml");
7+
8+
if (!fs.existsSync(sitemapIndexPath)) {
9+
console.log("[sitemap-alias] skipped: sitemap-index.xml was not found.");
10+
process.exit(0);
11+
}
12+
13+
const sitemapIndexXml = fs.readFileSync(sitemapIndexPath, "utf8");
14+
const locMatches = [...sitemapIndexXml.matchAll(/<loc>([^<]+)<\/loc>/g)];
15+
const childSitemapLocs = locMatches.map((match) => match[1].trim()).filter(Boolean);
16+
17+
let sourcePath = sitemapIndexPath;
18+
19+
if (childSitemapLocs.length === 1) {
20+
try {
21+
const childUrl = new URL(childSitemapLocs[0]);
22+
const childRelativePath = childUrl.pathname.replace(/^\//, "");
23+
const childSitemapPath = path.join(distDir, childRelativePath);
24+
if (fs.existsSync(childSitemapPath)) {
25+
sourcePath = childSitemapPath;
26+
}
27+
} catch {
28+
console.log(`[sitemap-alias] using index fallback: invalid child sitemap URL (${childSitemapLocs[0]}).`);
29+
}
30+
}
31+
32+
fs.copyFileSync(sourcePath, sitemapAliasPath);
33+
console.log(
34+
`[sitemap-alias] wrote sitemap.xml from ${path.basename(sourcePath)}.`
35+
);

src/layouts/BaseLayout.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const {
1616
} = Astro.props;
1717
const siteUrl = Astro.site ?? Astro.url;
1818
const baseUrl = new URL(import.meta.env.BASE_URL, siteUrl);
19-
const sitemapUrl = new URL("sitemap-index.xml", baseUrl).href;
19+
const sitemapUrl = new URL("sitemap.xml", baseUrl).href;
2020
const pathWithoutTrailingSlash = Astro.url.pathname.replace(/\/+$/, "") || "/";
2121
const defaultOgImage = `/og${pathWithoutTrailingSlash === "/" ? "/index" : pathWithoutTrailingSlash}.png`;
2222
const resolvedOgImage = ogImage ?? defaultOgImage;

src/pages/robots.txt.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import type { APIRoute } from "astro";
22

3-
const getRobotsTxt = (sitemapUrl: URL) => `User-agent: *
3+
const getRobotsTxt = (sitemapUrl: URL, sitemapIndexUrl: URL) => `User-agent: *
44
Allow: /
55
66
Sitemap: ${sitemapUrl.href}
7+
Sitemap: ${sitemapIndexUrl.href}
78
`;
89

910
export const GET: APIRoute = ({ site }) => {
@@ -12,9 +13,10 @@ export const GET: APIRoute = ({ site }) => {
1213
}
1314

1415
const siteWithBase = new URL(import.meta.env.BASE_URL, site);
15-
const sitemapUrl = new URL("sitemap-index.xml", siteWithBase);
16+
const sitemapUrl = new URL("sitemap.xml", siteWithBase);
17+
const sitemapIndexUrl = new URL("sitemap-index.xml", siteWithBase);
1618

17-
return new Response(getRobotsTxt(sitemapUrl), {
19+
return new Response(getRobotsTxt(sitemapUrl, sitemapIndexUrl), {
1820
headers: {
1921
"Content-Type": "text/plain; charset=utf-8",
2022
},

0 commit comments

Comments
 (0)