How to setup a dynamic sitemap.xml file on Netlify
I recently migrated my site to use Remix hosted on Netlify. I wanted to setup a dynamic sitemap.xml
file using Netlify functions. Remix already runs on a Netlify function, so I just created a separate function for returning the sitemap. Here’s how I did it.
- Create a new
sitemap
folder in yournetlify/functions
directory with anindex.ts
file inside that directory.
mkdir netlify/functions/sitemap
touch netlify/functions/sitemap/index.ts
- Inside your new
netlify/functions/sitemap/index.ts
file, create a new handler that returns a basic XML file with no content.
import type { Handler } from "@netlify/functions";
const handler: Handler = async () => {
const xmlContent = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
"</urlset>",
];
return {
statusCode: 200,
headers: { "Content-Type": "text/xml" },
body: xmlContent.join("\n"),
};
};
export { handler };
- To test this out, let’s add a redirect from
sitemap.xml
to our newly created function. We can add it as a new redirect in thenetlify.toml
file. You can read more about file based configuration with Netlify here.
[build]
command = "remix build"
functions = "netlify/functions"
publish = "public"
[dev]
command = "remix watch"
port = 3000
[[redirects]]
from = "/sitemap.xml"
to = "/.netlify/functions/sitemap"
status = 200
[[redirects]]
from = "/*"
to = "/.netlify/functions/server"
status = 200
[[headers]]
for = "/build/*"
[headers.values]
"Cache-Control" = "public, max-age=31536000, s-maxage=31536000"
Start up netlify dev
and make a request to localhost:<YOUR PORT>/sitemap.xml
.
You should see a basic XML file returned:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
</urlset>
- Add your URLs to the
sitemap.xml
file dynamically using Javascript.
import type { Handler } from "@netlify/functions";
const urls: Array<{ url: string; lastModified: string }> = [
{
url: "https://riegle.dev/",
lastModified: "2022-01-01",
},
{
url: "https://riegle.dev/blogs",
lastModified: "2022-01-01",
},
];
const handler: Handler = async () => {
const xmlContent = [
'<?xml version="1.0" encoding="UTF-8"?>',
'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
...urls.map(({ url, lastModified }) => {
return `
<url>
<loc>${url}</loc>
<lastmod>${lastModified}</lastmod>
</url>
`.trim();
}),
"</urlset>",
];
return {
statusCode: 200,
headers: {
"Content-Type": "text/xml",
},
body: xmlContent.join("\n"),
};
};
export { handler };
First, we define our site’s URLs in an array with both the URL and the last modified date. These are the only properties I care about on my site, but you can feel free to add any additional fields you want from the XML sitemap specification.
After we’ve created our list of URLs, we can add it to our xmlContent
array by mapping each URL into an XML string.
Wrapping up
Make sure you add all your URLs into the URL list and keep it updated as you add additional URLs/update existing pages. This will ensure your pages gets indexed correctly by search engines.