Generate sitemaps from your React Router configuration. Supports filtering paths, replacing dynamic params, and splitting large sitemaps automatically.
Supports: React 17–19, React Router 5–7 · Zero runtime dependencies
npm install @snaddyvitch-dispenser/react-router-sitemapimport Sitemap from '@snaddyvitch-dispenser/react-router-sitemap';
const routes = [
{ path: '/' },
{ path: '/about' },
{ path: '/contact' },
];
new Sitemap(routes)
.build('https://example.com')
.save('./public/sitemap.xml');Pass the route array directly from createBrowserRouter:
import Sitemap from '@snaddyvitch-dispenser/react-router-sitemap';
const routes = [
{ path: '/' },
{ path: '/about' },
{
path: '/blog',
children: [
{ path: ':slug' },
],
},
];
new Sitemap(routes).build('https://example.com').save('./sitemap.xml');import React from 'react';
import { Route } from 'react-router';
import Sitemap from '@snaddyvitch-dispenser/react-router-sitemap';
const router = (
<Route>
<Route path='/' />
<Route path='/about' />
<Route path='/contact' />
</Route>
);
new Sitemap(router).build('https://example.com').save('./sitemap.xml');Or using plain objects with childRoutes:
const routes = [
{ path: '/' },
{ path: '/about' },
{ path: '/blog', childRoutes: [{ path: ':slug' }] },
];Use filterPaths to exclude or include paths by regex rules.
new Sitemap(routes)
.filterPaths({
isValid: false, // false = exclude matches, true = include only matches
rules: [/\/auth/, /\/admin/],
})
.build('https://example.com')
.save('./sitemap.xml');Use applyParams to expand dynamic segments like :slug into real URLs.
const routes = [
{ path: '/blog/:slug' },
{ path: '/products/:category/:id' },
];
new Sitemap(routes)
.applyParams({
'/blog/:slug': [
{ slug: 'hello-world' },
{ slug: ['second-post', 'third-post'] },
],
'/products/:category/:id': [
{ category: 'shoes', id: ['1', '2', '3'] },
],
})
.build('https://example.com')
.save('./sitemap.xml');Google limits sitemaps to 50,000 URLs per file. When your site exceeds this, use limitCountPaths to split automatically. A sitemap index file is written to the dist path, with individual sitemaps written alongside it.
new Sitemap(routes)
.build('https://example.com', { limitCountPaths: 49999 })
.save('./public/sitemap.xml', '/static/');
// writes sitemap-0.xml, sitemap-1.xml, ... and sitemap.xml (index)Use build() to set defaults for all URLs, and applyMeta() to override per-path.
new Sitemap(routes)
.applyParams({ '/blog/:slug': [{ slug: 'hello' }, { slug: 'world' }] })
.applyMeta({
'/': { priority: 1.0, changefreq: 'daily' },
'/blog/:slug': { changefreq: 'monthly', priority: 0.7 }, // matches all resolved /blog/* paths
'/blog/hello': { lastmod: '2024-03-01' }, // exact match takes precedence
})
.build('https://example.com', {
changefreq: 'weekly', // default for all URLs not matched above
priority: 0.5,
})
.save('./sitemap.xml');applyMeta keys can be exact resolved paths or route param patterns (e.g. /blog/:slug). Exact matches take precedence over patterns. Fields not set are omitted from the XML entirely.
| Parameter | Type | Description |
|---|---|---|
router |
RouteConfig | RouteConfig[] | ReactElement |
React Router configuration |
| Parameter | Type | Description |
|---|---|---|
config.rules |
RegExp[] |
Patterns to match against paths |
config.isValid |
boolean |
true = keep matches, false = remove matches (default: false) |
Maps path patterns to arrays of param replacement objects. Each object's keys are param names (without :), values are a string or array of strings.
Maps resolved paths to metadata objects. Call after applyParams so paths are fully resolved. Per-path values take precedence over defaults set in build().
{
'/': { priority: 1.0, changefreq: 'daily', lastmod: '2024-01-15' },
'/blog': { changefreq: 'weekly' },
}| Parameter | Type | Default | Description |
|---|---|---|---|
hostname |
string |
Root URL of your site, e.g. 'https://example.com' |
|
options.limitCountPaths |
number |
49999 |
Max URLs per sitemap file |
options.lastmod |
string |
Default last modified date (ISO 8601) for all URLs | |
options.changefreq |
string |
Default change frequency for all URLs | |
options.priority |
number |
Default priority (0.0–1.0) for all URLs |
| Parameter | Type | Default | Description |
|---|---|---|---|
dist |
string |
Output path, e.g. './public/sitemap.xml' |
|
publicPath |
string |
'/' |
Public path prefix used in the sitemap index when splitting |
Types are included. Import them directly:
import Sitemap, { RouteConfig, FilterConfig, ParamsConfig } from '@snaddyvitch-dispenser/react-router-sitemap';