feat(publisher): generate sitemap.xml and robots.txt - #342
Open
artfusion wants to merge 1 commit into
Open
Conversation
Published sites had no crawler-facing route index. Adds two reserved public routes, resolved before the public-slug resolver: - GET /sitemap.xml — a urlset of every published, directly-routable URL with a <lastmod>: standalone pages plus content-row routes. - GET /robots.txt — allow-all except /admin, plus a Sitemap: line. Both derive from the published database per request; sitemaps are crawled infrequently and the response is cheap to rebuild. The route set mirrors what publicRouter will actually answer 200 for. Template pages (entry templates, everywhere layouts, the notFound page) are never directly routable, so they are excluded by checking isTemplatePage against the published SiteDocument. Content-row routes come from listPublishedRowRoutes — the same list a full publish bakes. Absolute URLs are anchored to the configured public origin matching the request host, falling back to the request origin when none is configured, so a TLS-terminating edge that forwards plain HTTP cannot leak http:// locs into crawler-facing output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Published sites currently have no crawler-facing route index. This adds two reserved public routes, resolved ahead of the public-slug resolver:
GET /sitemap.xml— aurlsetof every published, directly-routable URL with a<lastmod>: standalone pages plus content-row routes.GET /robots.txt— allow-all except/admin, plus aSitemap:line.Both derive from the published database per request. Sitemaps are crawled infrequently and the response is cheap to rebuild, so this deliberately avoids adding another artefact to the publish pipeline.
Two details worth reviewing:
The route set mirrors what
publicRouteractually answers 200 for. Template pages (entry templates,everywherelayouts, thenotFoundpage) are never directly routable, so they are excluded by checkingisTemplatePageagainst the publishedSiteDocument. A published page absent from the latest snapshot (an unusual incremental-publish edge) is kept, since it still resolves by slug and omitting it would hide a live URL. Content-row routes come fromlistPublishedRowRoutes— the same list a full publish bakes.Absolute URLs are anchored to the configured public origin, via a new
canonicalPublicOrigin(url)inserver/auth/security.ts. Behind a TLS-terminating edge the request URL scheme is plainhttp, so rawurl.originwould leakhttp://locs into crawler-facing output. A configured origin whose host matches the request host wins (multi-domain installs emit the domain the crawler actually fetched), else the canonical first entry, else the request origin when nothing is configured.The
vite.config.tschange opts both paths past the dev-proxy file-extension rejection, for the same reason as the existing/_instatic/routes.Developed against a live self-hosted install and currently serving that sites sitemap in production.
Verification
bun run buildbun testbun run lintbun testis 6581 pass / 1 fail. The single failure is theContentPage-*.jsbundle-size budget (89.1 kB vs 87.9 kB), which reproduces on a cleanmainwith none of this branch applied — pre-existing and unrelated to this change. The sitemap suite itself is 10/10.Checklist