Generating a sitemap

A sitemap is a file where you provide information about the pages, videos, and other files on your site and their relationships. Search engines like Google read this file to crawl your site more efficiently, helping with better search rankings. Search engines look for the sitemap at <your-website>/sitemap.xml.

In this article, we'll create a sitemap for your Frontastic project based on the product categories available.

📘

While this example uses the commercetools extension that ships with Frontastic, you can quickly adapt this example according to your project by changing the code to fetch the list of available paths.

As the Frontastic frontend is based on Next.js, we can create the /sitemap.xml route by creating a new file called sitemap.xml.js under the packages/frontend/pages directory of our project.

In this file, we define a function as the default export but leave the body empty because we'll use the getServerSideProps() function to generate the sitemap instead.

// required as default export by Next.js
function SiteMap() {
// empty function component  
}

export async function getServerSideProps({ request, response }) { 
// generate and return the sitemap
}

export default SiteMap;

To generate the sitemap, we need to fetch the available products from the API hubAPI hub - The API hub combines our code, your code, and APIs to create the backend of a commerce site. Any backend development or extensions are done here. Known as `Catwalk` in code. using the fetchApiHubServerSide helper function that lets us fetch data on the server-side:

import { fetchApiHubServerSide } from 'frontastic/lib/fetch-api-hub';

We'll use this function inside the getServerSideProps to fetch our product categories:

export async function getServerSideProps({ request, response }) {
  const categories = await fetchApiHubServerSide(`/action/product/queryCategories?limit=100`, { req, res });

  // we have the list of available categories
  console.log(categories)
  
  return {
    props: {},
  };
}

Now that we have the list of categories, we need to format it into an XML response. Let's create a helper function generateSiteMap which takes the host and categories as parameters and returns the XML string.

function generateSiteMap(host, categories) {
  return `<?xml version="1.0" encoding="UTF-8"?>
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <url>
       <loc>${host}</loc>
     </url>
     ${categories
       .map(({ slug }) => {
         return `
       <url>
           <loc>${`${host}/${slug}`}</loc>
       </url>
     `;
       })
       .join('')}
   </urlset>
 `;
}

export async function getServerSideProps({ request, response }) {
  const categories = await fetchApiHubServerSide(`/action/product/queryCategories?limit=100`, { req, res });

  // we generate the XML sitemap with the categories data
  const sitemap = generateSiteMap(request.headers.host, categories.items);

  return {
    props: {},
  };
}

The last step is to send the XML string as a response. We need to set the Content-Type header to text/xml to ensure the crawlers can read it correctly.

Here's the complete example:

import { fetchApiHubServerSide } from 'frontastic/lib/fetch-api-hub';

// no React component needs to be rendered because we send the response from the getServerSideProps itself
function SiteMap() {}

function generateSiteMap(host, categories) {
  return `<?xml version="1.0" encoding="UTF-8"?>
   <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
     <!--We manually set a URL we already know -->
     <url>
       <loc>${host}</loc>
     </url>
     ${categories
       .map(({ slug }) => {
         return `
       <url>
           <loc>${`${host}/${slug}`}</loc>
       </url>
     `;
       })
       .join('')}
   </urlset>
 `;
}

export async function getServerSideProps({ request, response }) {
  const categories = await fetchApiHubServerSide(`/action/product/queryCategories?limit=100`, { req, res });

  // we generate the XML sitemap with the categories data
  const sitemap = generateSiteMap(request.headers.host, categories.items);

  // we send the XML to the browser
  res.setHeader('Content-Type', 'text/xml');
  res.write(sitemap);
  res.end();

  return {
    props: {},
  };
}

export default SiteMap;

You can now validate the sitemap by visiting the <your-website>/sitemap.xml. It should look something like this:

🎉 Our sitemap is ready for the crawlers!🎉 Our sitemap is ready for the crawlers!

🎉 Our sitemap is ready for the crawlers!


Did this page help you?