[PR #399] [MERGED] feat: support generateSitemaps() for paginated sitemaps #542

Closed
opened 2026-05-06 13:08:40 +02:00 by BreizhHardware · 0 comments

📋 Pull Request Information

Original PR: https://github.com/cloudflare/vinext/pull/399
Author: @NathanDrake2406
Created: 3/10/2026
Status: Merged
Merged: 3/10/2026
Merged by: @james-elicx

Base: mainHead: feat/generate-sitemaps


📝 Commits (5)

  • c4c905b test: add products/sitemap.ts fixture with generateSitemaps
  • 9fba6df feat: support generateSitemaps() for paginated sitemaps
  • 0db02ea test: add integration tests for generateSitemaps and update snapshots
  • 80b4ba0 fix: address Codex review — typed id and single-segment matching
  • a470457 fix: address ask-bonk review feedback

📊 Changes

5 files changed (+283 additions, -3 deletions)

View changed files

📝 packages/vinext/src/entries/app-rsc-entry.ts (+28 -0)
📝 tests/__snapshots__/entry-templates.test.ts.snap (+168 -0)
📝 tests/app-router.test.ts (+60 -0)
tests/fixtures/app-basic/app/products/sitemap.ts (+22 -0)
📝 tests/shims.test.ts (+5 -3)

📄 Description

Summary

  • Adds support for Next.js's generateSitemaps() API for paginated sitemaps
  • When a sitemap.ts exports generateSitemaps(), individual sitemaps are served at /{segment}/sitemap/{id}.xml
  • The base URL (/{segment}/sitemap.xml) is no longer served when generateSitemaps exists (matches Next.js behavior)
  • Invalid IDs return 404 after validation against the generateSitemaps() result

How it works

The runtime metadata route handler in the generated RSC entry now checks if a sitemap module exports generateSitemaps. If so:

  1. URL matching: Instead of matching the exact servedUrl (e.g. /products/sitemap.xml), it matches the pattern /{prefix}/sitemap/{id}.xml
  2. ID validation: Calls generateSitemaps() and checks the requested ID exists in the returned array
  3. Rendering: Calls the default export with { id: rawId } and serializes with sitemapToXml()

Each paginated sitemap is a standalone <urlset> document. Next.js does not generate a <sitemapindex> — the issue description was incorrect about that part.

Note on the issue: #397 requested <sitemapindex> support, but Next.js doesn't implement that. Users who want a sitemap index can create a separate root sitemap.ts that manually lists the child sitemap URLs.

Closes #397

Test plan

  • GET /products/sitemap/0.xml → 200, XML with batch-0 entries only
  • GET /products/sitemap/1.xml → 200, XML with batch-1 entries only
  • GET /products/sitemap/99.xml → 404 (invalid ID)
  • GET /products/sitemap.xml → 404 (base URL not served with generateSitemaps)
  • scanMetadataFiles discovers nested products/sitemap.ts
  • Existing sitemap tests still pass (root /sitemap.xml without generateSitemaps)
  • All 214 app-router tests pass
  • Entry template snapshots updated
  • CI: format, lint, typecheck, vitest, playwright

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/cloudflare/vinext/pull/399 **Author:** [@NathanDrake2406](https://github.com/NathanDrake2406) **Created:** 3/10/2026 **Status:** ✅ Merged **Merged:** 3/10/2026 **Merged by:** [@james-elicx](https://github.com/james-elicx) **Base:** `main` ← **Head:** `feat/generate-sitemaps` --- ### 📝 Commits (5) - [`c4c905b`](https://github.com/cloudflare/vinext/commit/c4c905b6d567a903b546515cdd4e511d7df6866e) test: add products/sitemap.ts fixture with generateSitemaps - [`9fba6df`](https://github.com/cloudflare/vinext/commit/9fba6df470f5c6be2247ccfef57ca3edbf4f6800) feat: support generateSitemaps() for paginated sitemaps - [`0db02ea`](https://github.com/cloudflare/vinext/commit/0db02ead689245ad2966da2bb6015d3ff4c69d89) test: add integration tests for generateSitemaps and update snapshots - [`80b4ba0`](https://github.com/cloudflare/vinext/commit/80b4ba0a3e915aae121d0dc4bb201abecc4fad33) fix: address Codex review — typed id and single-segment matching - [`a470457`](https://github.com/cloudflare/vinext/commit/a470457271f08ce835fa4512bc60a309739263a8) fix: address ask-bonk review feedback ### 📊 Changes **5 files changed** (+283 additions, -3 deletions) <details> <summary>View changed files</summary> 📝 `packages/vinext/src/entries/app-rsc-entry.ts` (+28 -0) 📝 `tests/__snapshots__/entry-templates.test.ts.snap` (+168 -0) 📝 `tests/app-router.test.ts` (+60 -0) ➕ `tests/fixtures/app-basic/app/products/sitemap.ts` (+22 -0) 📝 `tests/shims.test.ts` (+5 -3) </details> ### 📄 Description ## Summary - Adds support for Next.js's [`generateSitemaps()`](https://nextjs.org/docs/app/api-reference/functions/generate-sitemaps) API for paginated sitemaps - When a `sitemap.ts` exports `generateSitemaps()`, individual sitemaps are served at `/{segment}/sitemap/{id}.xml` - The base URL (`/{segment}/sitemap.xml`) is no longer served when `generateSitemaps` exists (matches Next.js behavior) - Invalid IDs return 404 after validation against the `generateSitemaps()` result ## How it works The runtime metadata route handler in the generated RSC entry now checks if a sitemap module exports `generateSitemaps`. If so: 1. **URL matching**: Instead of matching the exact `servedUrl` (e.g. `/products/sitemap.xml`), it matches the pattern `/{prefix}/sitemap/{id}.xml` 2. **ID validation**: Calls `generateSitemaps()` and checks the requested ID exists in the returned array 3. **Rendering**: Calls the default export with `{ id: rawId }` and serializes with `sitemapToXml()` Each paginated sitemap is a standalone `<urlset>` document. Next.js does not generate a `<sitemapindex>` — the issue description was incorrect about that part. **Note on the issue**: #397 requested `<sitemapindex>` support, but Next.js doesn't implement that. Users who want a sitemap index can create a separate root `sitemap.ts` that manually lists the child sitemap URLs. Closes #397 ## Test plan - [x] `GET /products/sitemap/0.xml` → 200, XML with batch-0 entries only - [x] `GET /products/sitemap/1.xml` → 200, XML with batch-1 entries only - [x] `GET /products/sitemap/99.xml` → 404 (invalid ID) - [x] `GET /products/sitemap.xml` → 404 (base URL not served with generateSitemaps) - [x] `scanMetadataFiles` discovers nested `products/sitemap.ts` - [x] Existing sitemap tests still pass (root `/sitemap.xml` without generateSitemaps) - [x] All 214 app-router tests pass - [x] Entry template snapshots updated - [x] CI: format, lint, typecheck, vitest, playwright --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
BreizhHardware 2026-05-06 13:08:40 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#542
No description provided.