Skip to content

[template] sitemap: paged shards matching Hydrogen's model#311

Merged
laugharn merged 7 commits into
release-2026-06-07from
template-sitemap-hydrogen-parity
Jun 8, 2026
Merged

[template] sitemap: paged shards matching Hydrogen's model#311
laugharn merged 7 commits into
release-2026-06-07from
template-sitemap-hydrogen-parity

Conversation

@laugharn
Copy link
Copy Markdown
Collaborator

@laugharn laugharn commented Jun 4, 2026

Summary

  • Replaces the single-XML sitemap (every product handle eagerly loaded, collections capped at 250) with a sitemap index + paged children backed by Shopify's Storefront sitemap(type:) query — same model Hydrogen uses
  • New URL shape: /sitemap.xml (index) + /sitemap/{static,products-{n},collections-{n}}.xml (children, ≤250 entries each)
  • Implemented as plain route handlers, not app/sitemap.ts + generateSitemaps: Next.js 16 reserves /sitemap.xml for the metadata file even though generateSitemaps doesn't actually emit a sitemap index there, so the two collide. Owning both routes manually sidesteps that

Why

  • Stores with more than 250 collections were silently truncated
  • Stores with tens of thousands of products generated a single multi-MB XML that breached Google's 50k-URLs-per-file cap and risked OOM during prerender
  • The Storefront sitemap query is purpose-built for this — Shopify computes the pagination, ≤250 items per page

Deliberately not in scope

  • Pages, blogs, articles, metaobjects
  • Locale alternates / Shopify Markets
  • Image-sitemap extensions: Shopify's Sitemap.image.filepath is a path fragment, but <image:loc> requires an absolute URL. Resolving the CDN base is left as future work — noted in the rollout entry

Test plan

  • pnpm --filter template build — clean; /sitemap.xml prerenders, /sitemap/[shard] is dynamic + cache-tagged
  • curl /sitemap.xml<sitemapindex> listing every shard
  • curl /sitemap/static.xml<urlset> with the home URL
  • curl /sitemap/products-1.xml<urlset> of products with <loc> + <lastmod>
  • curl /sitemap/collections-1.xml<urlset> of collections
  • Spot-check shard product count vs. Shopify admin total
  • Verify cache invalidation: mutate a product, confirm next sitemap fetch refreshes

🤖 Generated with Claude Code

Replaces the single eagerly-loaded sitemap (every product handle in one
XML, plus the first 250 collections only) with a sitemap index + paged
child sitemaps backed by Shopify's Storefront `sitemap(type:)` query.

- /sitemap.xml — index listing every shard
- /sitemap/static.xml — home
- /sitemap/products-{n}.xml — up to 250 products per shard
- /sitemap/collections-{n}.xml — same for collections

`getAllProductHandles` is gone; new ops are `getShopifySitemapPagesCount`
and `getShopifySitemapPage`. Implemented as plain route handlers because
Next.js 16 reserves /sitemap.xml for app/sitemap.ts even when
generateSitemaps doesn't auto-emit a sitemap index there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Jun 4, 2026

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

Project Deployment Actions Updated (UTC)
shop-docs Ready Ready Preview, Comment Jun 8, 2026 12:51am
shop-template Ready Ready Preview, Comment, Open in v0 Jun 8, 2026 12:51am

Adds anatomy/sitemap.mdx documenting the index + paged-shard URLs,
cache behavior, and how to extend to more SitemapType resources.
Updates anatomy/aeo-geo.mdx to point at the new route handler paths
instead of the deleted app/sitemap.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread apps/docs/content/docs/anatomy/sitemap.mdx Outdated
Three skills walked through editing app/sitemap.ts directly. After the
refactor that file no longer exists; updates point at the new route
handlers and gesture at how to extend them:

- enable-i18n: Step 8 per-locale sitemap now describes editing
  app/sitemap/[shard]/route.ts to emit xhtml:link alternates per <url>.
  Verifying step curls a child shard, not just the index.
- enable-shopify-markets: same Step 12 update; also fixes the
  middleware matcher to exclude /sitemap/ children, not just
  /sitemap.xml (otherwise the locale rewrite would catch child shards).
- enable-shopify-cms: one-line path fix; gestures at adding a
  cms-pages-{n} shard for indexing CMS pages.

apps/docs/content/docs/skills/*.mdx synced via sync-skills.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
laugharn and others added 3 commits June 7, 2026 19:34
# Conflicts:
#	apps/docs/content/docs/anatomy/aeo-geo.mdx
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Key files section listed `/sitemap.xml` (a URL) which the
path linter resolved as a file. Reworded to drop the path-like token.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The index route hardcodes product and collection shards; it does not
discover new SitemapTypes automatically. Document the count-fetch +
child-id edit in sitemap.xml/route.ts as a required third step.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@laugharn laugharn merged commit d09238c into release-2026-06-07 Jun 8, 2026
6 checks passed
@laugharn laugharn mentioned this pull request Jun 8, 2026
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