SEO
Sitemaps
How to generate sitemaps for search engine discovery
Sitemaps help search engines discover and index your pages. The generateSitemap function creates a Next.js-compatible sitemap.
Basic Usage
import { } from "@startupkit/seo"
export default function () {
return ({
: "https://myapp.com",
: [
{ : "/" },
{ : "/about" },
{ : "/pricing" },
{ : "/blog" },
{ : "/contact" }
]
})
}This generates /sitemap.xml:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://myapp.com/</loc>
<lastmod>2024-01-15</lastmod>
<changefreq>daily</changefreq>
<priority>1</priority>
</url>
<url>
<loc>https://myapp.com/about</loc>
<lastmod>2024-01-15</lastmod>
<changefreq>daily</changefreq>
<priority>1</priority>
</url>
...
</urlset>Route Configuration
Basic Route
{ path: "/about" }With Priority
Higher priority pages (0.0 to 1.0):
{ path: "/", priority: 1.0 }, // Homepage - highest
{ path: "/pricing", priority: 0.9 },
{ path: "/about", priority: 0.8 },
{ path: "/contact", priority: 0.5 }With Change Frequency
How often the page changes:
{ path: "/", changeFrequency: "daily" },
{ path: "/blog", changeFrequency: "weekly" },
{ path: "/about", changeFrequency: "monthly" },
{ path: "/terms", changeFrequency: "yearly" }Options: always, hourly, daily, weekly, monthly, yearly, never
With Last Modified
{
path: "/blog/my-post",
lastModified: new Date("2024-01-15")
}Dynamic Sitemaps
Blog Posts
import { } from "@startupkit/seo"
import { } from "@repo/db"
export default async function () {
const = await .query.posts.findMany({
: { : true, : true }
})
const = .map( => ({
: `/blog/${.slug}`,
: .updatedAt,
: "weekly" as ,
: 0.7
}))
return ({
: "https://myapp.com",
: [
{ : "/", : 1.0 },
{ : "/blog", : 0.9 },
...
]
})
}Product Pages
import { } from "@startupkit/seo"
export default async function () {
const = await fetchProducts()
const = .map( => ({
: `/products/${.slug}`,
: .updatedAt,
: 0.8
}))
return ({
: "https://myapp.com",
: [
{ : "/", : 1.0 },
{ : "/products", : 0.9 },
...
]
})
}Multiple Sitemaps (Sitemap Index)
For large sites with more than 50,000 URLs, split into multiple sitemaps using Next.js's built-in sitemap index support:
import type { MetadataRoute } from "next"
declare function (): <number>
declare function (: { : number; : number }): <{ : string; : Date }[]>
export async function () {
const = await ()
const = .( / 50000)
return .({ : }, (, ) => ({ : }))
}
export default async function ({
}: {
: number
}): <MetadataRoute.> {
const = * 50000
const = await ({ , : 50000 })
return .( => ({
: `https://myapp.com/products/${.}`,
: .
}))
}This automatically generates:
/sitemap.xml— the sitemap index listing all child sitemaps/sitemap/0.xml,/sitemap/1.xml, etc. — individual sitemaps with up to 50,000 URLs each
Category-Based Sitemaps
You can also organize sitemaps by content type:
import type { MetadataRoute } from "next"
declare function (): <{ : string; : Date }[]>
declare function (): <{ : string; : Date }[]>
const = ["main", "blog", "products"] as
export async function () {
return .( => ({ }))
}
export default async function ({
}: {
: string
}): <MetadataRoute.> {
switch () {
case "main":
return [
{ : "https://myapp.com", : 1.0 },
{ : "https://myapp.com/about", : 0.8 },
{ : "https://myapp.com/pricing", : 0.9 }
]
case "blog":
const = await ()
return .( => ({
: `https://myapp.com/blog/${.}`,
: .
}))
case "products":
const = await ()
return .( => ({
: `https://myapp.com/products/${.}`,
: .
}))
default:
return []
}
}
## Parameters
### generateSitemap
```tsx
generateSitemap({
baseUrl: string, // Full base URL (e.g., "https://myapp.com")
routes: SitemapRoute[]
})SitemapRoute
| Field | Type | Default | Description |
|---|---|---|---|
path | string | Required | URL path (e.g., /about) |
lastModified | Date | new Date() | Last modification date |
changeFrequency | string | "daily" | How often page changes |
priority | number | 1 | Importance (0.0 - 1.0) |
Best Practices
Priority Guidelines
| Page Type | Priority |
|---|---|
| Homepage | 1.0 |
| Core pages (pricing, features) | 0.9 |
| Product/category pages | 0.8 |
| Blog posts | 0.7 |
| Support/docs | 0.6 |
| Legal pages | 0.3 |
Exclude Pages
Don't include in sitemap:
- Auth pages (
/sign-in,/sign-up) - Dashboard/app pages
- API routes
- Error pages (
/404,/500) - Redirects
Keep Updated
Update lastModified when content changes:
const = await .query.posts.findMany()
const = .map( => ({
: `/blog/${.slug}`,
: .updatedAt // Actual update date
}))Submitting to Search Engines
Google Search Console
- Go to Search Console
- Add your property
- Navigate to Sitemaps
- Enter
sitemap.xml - Click Submit
Bing Webmaster Tools
- Go to Bing Webmaster
- Add your site
- Submit sitemap URL
robots.txt Reference
Include sitemap in robots.txt:
Sitemap: https://myapp.com/sitemap.xmlSee Robots.txt for more.
Debugging
Check Sitemap
Visit https://myapp.com/sitemap.xml directly.
Validate Format
Check in Search Console
Google Search Console shows sitemap status and any errors.
Next Steps
- Robots.txt - Control crawler access
- Page metadata - Optimize individual pages