Create a sitemap with Remix.run

A sitemap is important if you have content on your website. It's a file that'll let the Search Engines know about all your content. It's often exposed at a domain.com/sitemap.xml route.

You can find all the documentation you need about sitemaps on sitemaps.org.

The TL;DR; version of it is that a sitemap looks like this :

sitemap.xml

_16
<?xml version="1.0" encoding="UTF-8"?>
_16
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
_16
<url>
_16
<loc>http://www.example.com/</loc>
_16
<lastmod>2005-01-01</lastmod>
_16
<changefreq>monthly</changefreq>
_16
<priority>0.8</priority>
_16
</url>
_16
<url>
_16
<loc>http://www.example.com/blog</loc>
_16
<changefreq>weekly</changefreq>
_16
</url>
_16
<url>
_16
<loc>http://www.example.com/contact</loc>
_16
</url>
_16
</urlset>

This format will work in most cases.

Let's get started by creating a new route in our Remix app. We want the URL of our sitemap to be sitemap.xml.

To create this route we need to create a file in app/routes/[sitemap.xml].ts. The [] syntax is a convention in Remix routes to escape the content. This allows us to treat .xml as part of the URL.

You can learn more about this syntax in the Route File Convention.

In this route we'll just need to export a loader that returns an XML response.

app/routes/[sitemap.xml].ts

_12
export async function loader() {
_12
const sitemap = null
_12
_12
// Generate the sitemap
_12
_12
return new Response(sitemap, {
_12
headers: {
_12
'Content-Type': 'application/xml',
_12
'Cache-Control': 'public, max-age=86400', // Cache for a day
_12
},
_12
})
_12
}

This will make the sitemap.xml route available, and will return an empty XML response.

We now need to generate the sitemap content.

Let's start by defining the type of a Sitemap Entry using Typescript.

app/routes/[sitemap.xml].ts

_13
export type SitemapEntry = {
_13
loc: string
_13
lastmod?: string
_13
changefreq?:
_13
| 'always'
_13
| 'hourly'
_13
| 'daily'
_13
| 'weekly'
_13
| 'monthly'
_13
| 'yearly'
_13
| 'never'
_13
priority?: string
_13
}