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.

Why automate your sitemap?

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 or virtual: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:

app/routes/sitemap.xml.ts
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?

  1. 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 your routes object from it.

  2. 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 be virtual:react-router/server-build. That’s why we have to import the routes in the previous step by hand. I already opened an issue to get native support for React Router 7.

  3. The ignore option excludes routes you don’t want indexed (like API endpoints or legal pages).
    Why ignore some routes?

    Not every route should be indexed by search engines. Exclude API endpoints, admin pages, or anything private.

    I prefer using the 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.

  4. The domain option specifies the domain for your URLs. Using the request’s origin should work in any environment.
  5. 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:

app/routes.ts
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!

Duplicate route registration

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.