Sitemap planner
Describe your page tiers and get a priority ladder, a change frequency mapping, a lastModified strategy per tier, and the sitemap composer that implements it.
| Tier | Path | URLs | Priority | Change frequency | lastModified source |
|---|---|---|---|---|---|
1,755 URLs across 6 tiers, using 6 distinct priority values. Four or more is the point at which the ladder communicates something; a flat value communicates nothing.
Your app/sitemap.ts
// app/sitemap.ts
import type { MetadataRoute } from "next";
import { buildSitemap, PRIORITY } from "@/kit/seo/sitemap";
import { SITE_URL } from "@/lib/seo";
export default function sitemap(): MetadataRoute.Sitemap {
return buildSitemap(
[
{
name: "home",
items: HOME,
url: (item) => `/`,
// Manual, on redesign. Never new Date().
lastModified: (item) => item.updatedAt,
priority: PRIORITY.home,
changeFrequency: "weekly",
},
{
name: "pricing",
items: PRICING,
url: (item) => `/pricing`,
// Pricing module change. Never new Date().
lastModified: (item) => item.updatedAt,
priority: PRIORITY.primaryConversion,
changeFrequency: "monthly",
},
{
name: "docs-or-chapters",
items: DOCS_OR_CHAPTERS,
url: (item) => `/docs/${item.slug}`,
// Frontmatter updatedAt. Never new Date().
lastModified: (item) => item.updatedAt,
priority: PRIORITY.primaryContent,
changeFrequency: "monthly",
},
{
name: "programmatic-tier",
items: PROGRAMMATIC_TIER,
url: (item) => `/entity/${item.slug}`,
// Snapshot generation timestamp. Never new Date().
lastModified: (item) => item.updatedAt,
priority: PRIORITY.programmatic,
changeFrequency: "monthly",
},
{
name: "blog",
items: BLOG,
url: (item) => `/blog/${item.slug}`,
// Post updatedAt, falling back to publishedAt. Never new Date().
lastModified: (item) => item.updatedAt,
priority: PRIORITY.editorial,
changeFrequency: "monthly",
},
{
name: "legal",
items: LEGAL,
url: (item) => `/terms`,
// Manual, on revision. Never new Date().
lastModified: (item) => item.updatedAt,
priority: PRIORITY.legal,
changeFrequency: "yearly",
},
],
{ siteUrl: SITE_URL, languages: ["en-US", "x-default"] },
);
}
How to use it
- 01List your tiersOne row per page type, with the number of URLs it produces.
- 02Set a priority per tierPriority is a relative hint inside one site. Four or more distinct values communicate a hierarchy; a flat value communicates nothing.
- 03Name where each date comes fromThis is the column that matters. Every lastModified has to come from the content, never from the build.
- 04Copy the generated composerIt requires a lastModified accessor per group, which makes a build stamp difficult to introduce by accident.
Questions
Does Google use sitemap priority?
Google ignores both priority and changefreq. They remain useful as internal documentation of which pages you consider most important, and other crawlers may read them.
Why does lastModified matter so much?
Google uses the lastmod value only when it is consistently accurate. A build timestamp on every URL teaches the crawler that the field carries no information, and that trust is not recovered by fixing it later.
How do I tell whether my sitemap is build-stamped?
Extract every lastmod value, reduce it to a date, and count occurrences per day. If a single day covers most of your URLs, it is a build stamp rather than content dates.
Where this comes from
This tool uses the same modules SEO for Solos sells in the Code Kit, so the output and the product cannot diverge. The reasoning behind it is in the playbook.