Generating sitemaps for react apps is much more complex that it should be.

If your app is basic with a few routes, then you can add a simple static sitemap file inside your public folder and call it done.

I have somewhat dynamic content, so I need a somewhat dynamic solution, and thankfully my hosting provider netlify has free netlify function.

1. Return static data

Netlify will not currently allow a streaming response, so we have to figure out a static xml response.

Inside your functions folder, add /functions/sitemap.js

exports.handler = function(event, context, callback) {
  var xml_content = [
    '<?xml version="1.0" encoding="UTF-8"?>',
    '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
    `<url><loc>https://www.blairanderson.co/</loc></url>`,
    // `<url><loc>add more pages here</loc></url>`,
    "</urlset>"
  ];

  callback(null, {
    statusCode: 200,
    headers: { "Content-Type": "text/xml" },
    body: xml_content.join("\n")
  });
};

push to netlify, and this is a perfectly acceptable sitemap to submit to google!

2. Return dynamic data

If any part of your site is dynamic, maybe you have a CRUD form and want to have a page for each comment that is user-generated-content.

You might want use an API to hold your comments, and return them when people visit.

This is a scenario you might want to add them to a sitemap, and also use that API to fetch the full list of comments or something like that.

var https = require("https");

var API_DATA_URL = "https://www.someexampledata.com/comments.json";

exports.handler = function(event, context, callback) {
  var xml_content = [
    '<?xml version="1.0" encoding="UTF-8"?>',
    '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
  ];

  https
    .get(API_DATA_URL, resp => {
      let data = "";

      // A chunk of data has been recieved.
      resp.on("data", chunk => {
        data += chunk;
      });

      // The whole response has been received. Print out the result.
      resp.on("end", () => {
        var json = JSON.parse(data);

        var list = json.listOfExampleThings.map(function(el) {
          return `<url><loc>https://www.site.com/comment/${el.id}</loc></url>`;
        });

        var body = xml_content
          .concat(list)
          .concat("</urlset>")
          .join("\n");

        callback(null, {
          statusCode: 200,
          headers: { "Content-Type": "text/xml" },
          body: body
        });
      });
    })
    .on("error", err => {
      console.log("Error: " + err.message);
    });
};

The best part about this is that you do not need to worry about any package management or modules because https is built into node!