How to generate a Sitemap in React Router 7 and Remix

Learn how to automatically generate a sitemap.xml file for your React Router 7 or Remix app using minimal configuration with this step-by-step guide.
If you’re building a website or web application, you’ll want to make sure your site is discoverable by search engines. One essential step is providing a sitemap that lists all your public routes.
Manually maintaining a sitemap is tedious and error-prone. By generating it from your route definitions, you ensure it’s always up-to-date and accurate.
#Prerequisites
- A project using React Router 7 or Remix.
- Access to your route definitions via
virtual:react-router/server-build
orvirtual:remix/server-build
.
#Install the @forge42/seo-tools
package
First, install the @forge42/seo-tools package. This library provides utilities for handling SEO-related tasks and has a dedicated @forge42/seo-tools/remix
export that works with Remix and React Router 7 applications.
npm install @forge42/seo-tools
#Create the resource route for the sitemap
Create a file at app/routes/sitemap.xml.ts
. This will be the resource route and exports a loader
that generates the sitemap on demand:
import { generateRemixSitemap } from "@forge42/seo-tools/remix/sitemap";
import type { Route } from "./+types/sitemap.xml";
import { href } from "react-router";
export const loader = async ({ request }: Route.LoaderArgs) => {
const { routes } = await import("virtual:react-router/server-build");
const { origin } = new URL(request.url);
const sitemap = await generateRemixSitemap({
domain: origin,
ignore: [href("/api/chat"), href("/legal-notice"), href("/privacy-policy")],
// @ts-expect-error Type mismatch, maybe related to a stricter type mentioned in release notes for v.7.0.0
// https://github.com/forge-42/seo-tools/issues/8
routes,
});
return new Response(sitemap, {
headers: {
"Content-Type": "application/xml",
},
});
};
#What’s happening here?
- Dynamically import
virtual:react-router/server-build
to get your route definitions.Info Since React Router v7.4.0, the
virtual:react-router/server-build
module is type safe and you can destructure yourroutes
object from it. - The
generateRemixSitemap()
helper function takes your route definitions and creates a valid sitemap.Info Because the package is build for Remix v2, the function automatically looks for routes in
virtual:remix/server-build
, but with React Router 7, the correct module would bevirtual:react-router/server-build
. That’s why we have to import theroutes
in the previous step by hand. I already opened an issue to get native support for React Router 7. - The
ignore
option excludes routes you don’t want indexed (like API endpoints or legal pages).I prefer using theWhy ignore some routes? Not every route should be indexed by search engines. Exclude API endpoints, admin pages, or anything private.
href()
function from React Router 7 for type-safe paths.Tip The
href
function was introduced in React Router v7.2.0 and ensures type safety for your links. - The
domain
option specifies the domain for your URLs. Using the request’sorigin
should work in any environment. - The response returns the sitemap as XML with the correct content type.
For more information and advanced usage, check out the official documentation.
#Register the route
Make sure the route is included in your route config:
export default [
// ...
route("sitemap.xml", "routes/sitemap.xml.ts"),
] satisfies RouteConfig;
Now, visiting /sitemap.xml
in your browser will return a fresh, up-to-date sitemap!
When using the package, I found the home route (/
) was registered multiple
times in the sitemap. See issue
#12.
#Test your sitemap
Visit /sitemap.xml
in your browser or use an online validator to check that your sitemap is valid and includes all the right routes.
#Submit the sitemap to search engines
To have your sitemap indexed, you should submit it to search engines. Most will discover it if you link to it from your robots.txt
, but submitting directly is more reliable.
- For Google, use Search Console.
- For Bing, use Bing Webmaster Tools.