<?xml version="1.0" encoding="UTF-8"?>
<!--
  Ten URLs: the two static pages, and the eight routes the decision gate in
  docs/routing-plan.md is measuring.

  GUIDES BELONG HERE TOO, ONCE ANY ARE PUBLISHED — one <loc> for /guides and one
  per article. The section is built and deliberately dark: nothing in
  content/guides has lost its `draft: true` yet, so build-guides.mjs writes no
  pages, vite.config.js leaves the Guides link out of the menu, and listing a
  URL here would advertise a 404.

  When the first guide ships, three files change together: this one, the
  rewrites in firebase.json, and the markdown itself. That is not a convention
  to remember — tests/guides-routes.test.js fails if any of the three disagree
  in either direction.

  Guides will not confound the measurement below when they arrive. They are real
  static HTML, so a crawler needs no JavaScript to read a word of them and
  whether they index was never the open question; Search Console reports status
  per URL, and they are a disjoint family from the eight. The one caution is the
  site-wide Coverage chart, which mixes everything — read per-URL status when
  answering the gate. See docs/routing-plan.md.

  /bot is a third static page and is deliberately NOT listed here. It is the
  crawler disclosure that CreaseDealsBot's User-Agent points at — unlisted,
  reachable by anyone with the URL, and carrying its own noindex tag. Adding it
  to this file would undo that. It is also not disallowed in robots.txt, on
  purpose: see the comment in bot.html.

  THE EIGHT ROUTES ARE AN EXPERIMENT, NOT A FORMALITY. They are client-rendered
  by App.jsx — Google executes JavaScript and can index such routes, less
  reliably and more slowly than static HTML. Whether it actually does is the
  one open question the whole of Stage B is gated on. Four to six weeks after
  this ships, Search Console answers it: indexed means the search surface
  exists for a fraction of the work and Stage B never happens; not indexed
  means prerendering is demonstrably required rather than assumed.

  Why these eight and not all 136 routable combinations. They are the head,
  measured against the live feed of 2026-08-12 (768 deals, post-dedupe):
  apparel 317, nike 116, new-balance 103, warrior 95, heads 93, pads 92,
  sticks 89, cleats 83. Every one sits an order of magnitude clear of any
  sensible threshold, so this file is effectively static and nothing here
  oscillates in and out. The long tail is where the complexity lives and it
  holds the least value.

  Do not add the tail to make the list look thorough. A sitemap of near-empty
  near-identical pages is how a site gets demoted for thin content, and it
  would also wreck the measurement above — a route failing to index because it
  is thin looks identical to one failing because Google could not render it,
  and those have opposite answers.

  Every URL here is also reachable by a real <a href> on the site: categories
  from the chip row in App.jsx, brands from the brand line on each deal card.
  That is deliberate and load-bearing. A sitemap-only URL is an orphan, and an
  orphan that goes unindexed tells you nothing about whether rendering worked.

  Retailer, sort, price and search stay out permanently. They are reorderings
  and continuous ranges — routing them builds a crawl trap of near-identical
  pages, which is the failure this list is shaped to avoid.

  No <lastmod>. The deals on / change daily, and a hand-maintained date in a
  static file would be wrong within a day of being written — Google discounts
  lastmod it finds unreliable, so a stale one is worse than none. If this ever
  needs to be accurate, generate the file at build time or serve it from a
  function the way /feed.json is served. <changefreq> and <priority> are
  omitted for a simpler reason: Google ignores both.
-->
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://creasedeals.com/</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/about</loc>
  </url>

  <!-- Guides go here, one <loc> for /guides and one per published article,
       when there is a published article. There is not yet: the section is built
       but dark on purpose, and tests/guides-routes.test.js fails if this file
       and content/guides ever disagree in either direction. -->

  <!-- Categories, largest first. -->
  <url>
    <loc>https://creasedeals.com/apparel</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/heads</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/pads</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/sticks</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/cleats</loc>
  </url>

  <!-- Brands. Slugs are pinned in web/src/routes.js and must never be edited
       to match a changed display name — that is the whole reason they are
       stored rather than derived. If one has to change, keep a redirect. -->
  <url>
    <loc>https://creasedeals.com/brand/nike</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/brand/new-balance</loc>
  </url>
  <url>
    <loc>https://creasedeals.com/brand/warrior</loc>
  </url>
</urlset>
