Skip to content

fix(sitemap): generate sitemap.xml under Yarn and gate it in CI - #126

Merged
ahnafnafee merged 1 commit into
mainfrom
fix/sitemap-yarn4-generation
Jul 28, 2026
Merged

fix(sitemap): generate sitemap.xml under Yarn and gate it in CI#126
ahnafnafee merged 1 commit into
mainfrom
fix/sitemap-yarn4-generation

Conversation

@ahnafnafee

Copy link
Copy Markdown
Owner

Problem

https://www.ahnafnafee.dev/sitemap.xml returns HTTP 404. Browsers report it as an XML parsing error because they are parsing the Next.js HTML 404 page.

next-sitemap was wired to the postbuild npm lifecycle hook. CI and Vercel both build with Yarn 4 (packageManager: yarn@4.14.1, corepack in vercel.json), and Yarn does not run pre/post scripts for user-defined commands:

yarn run build  ->  BUILD RAN
npm  run build  ->  PREBUILD RAN / BUILD RAN / POSTBUILD RAN

So the sitemap was never generated. public/sitemap.xml is gitignored (**/public/*.xml), so there was no committed fallback, and the committed robots.txt kept pointing at the missing file. prebuild was dead for the same reason, leaving public/llms.txt six blog posts behind.

Summary

  • Chain generate:llms and generate:sitemap explicitly inside build instead of relying on lifecycle hooks, so they run under any package manager.
  • Add scripts/validate-sitemap.js and a Validate sitemap CI step after the build. It runs on the same package manager Vercel uses, so it fails on exactly this regression.
  • Resolve site-relative frontmatter images against siteUrl, recovering 4 portfolio entries that were being dropped from <image:loc> (27 -> 31 images).
  • Regenerate the stale public/llms.txt.

What the gate checks

File exists, is not an HTML error page, has no unescaped &, parses as well-formed XML, root is <urlset> with at least one <url>, every <loc> and <image:loc> is an absolute https URL, no duplicate locs, no localhost, and the Sitemap: origin in robots.txt matches.

Test plan

  • yarn build from a deleted public/sitemap.xml regenerates it
  • yarn validate:sitemap passes on real output (36 URLs, 31 images)
  • Gate exits 1 on each failure mode: missing file, HTML 404 page, unescaped &, malformed XML, localhost/non-https loc, duplicate loc, empty urlset, robots.txt origin mismatch
  • yarn type-check, yarn lint, yarn test (66 passing)
  • CI green on this PR
  • After deploy, confirm /sitemap.xml returns 200 XML (the current 404 is cached with a 24h Cache-Control)

next-sitemap ran from the `postbuild` npm lifecycle hook, but CI and Vercel
both build with Yarn 4, which does not run pre/post scripts for user-defined
commands. The sitemap was therefore never generated: /sitemap.xml fell through
to the Next.js HTML 404 page, which every XML client reports as a parse error.
public/sitemap.xml is gitignored, so there was no committed fallback, while the
committed robots.txt kept advertising the missing file. `prebuild` was dead for
the same reason, leaving llms.txt frozen six posts behind.

Chain both generators explicitly at the ends of `build` so they run under any
package manager, and add `yarn validate:sitemap` as a CI gate immediately after
the build step: the sitemap must exist, must not be an HTML error page, must
parse as XML with no unescaped entities, and must carry absolute canonical URLs
whose origin matches the Sitemap: line in robots.txt.

Also resolve site-relative frontmatter images against siteUrl, so the four
portfolio entries using /images/*.png stop being dropped from <image:loc>.
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ahnafnafee-dev Ready Ready Preview, Comment Jul 28, 2026 3:28pm

@ahnafnafee
ahnafnafee merged commit e0a8c27 into main Jul 28, 2026
6 checks passed
@ahnafnafee
ahnafnafee deleted the fix/sitemap-yarn4-generation branch July 28, 2026 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant