DEV Community

Cover image for How to Generate Dynamic Sitemaps in Next.js
TnvMadhav⚡
TnvMadhav⚡

Posted on • Originally published at tnvmadhav.me

How to Generate Dynamic Sitemaps in Next.js

Introduction

Let's say you have folder containing markdown files which are used as individual blog posts in the Next.js blog website.

This is exactly what I did to generate sitemap.xml file for my Next.js website https://notionworkspaces.com/

Steps to generate sitemap.xml (only 3 steps)

  1. Create a sitemap.xml.js file inside src/pages/ folder from the Next.js home directory
  2. Add this code inside it
import fs from 'fs';
import matter from 'gray-matter';

const postsDirectory = path.join(process.cwd(), 'posts');

const URL = "https://yourwebsitedomain.com";

function generateSiteMap(posts) {
  return `<?xml version="1.0" encoding="UTF-8"?>
   <urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
     <!-- Add the static URLs manually -->
     <url>
       <loc>${URL}</loc>
     </url>
     ${posts
       .map(({ id }) => {
         return `
           <url>
               <loc>${`${URL}/posts/${id}`}</loc>
               <lastmod>${new Date().toISOString()}</lastmod>
           </url>
         `;
       })
       .join("")}
   </urlset>
 `;
}

export function getSortedPostsData() {
  // Get file names under /posts
  const fileNames = fs.readdirSync(postsDirectory);
  const allPostsData = fileNames.map((fileName) => {
    // Remove ".md" from file name to get id
    const id = fileName.replace(/\.md$/, '');

    // Read markdown file as string
    const fullPath = path.join(postsDirectory, fileName);
    const fileContents = fs.readFileSync(fullPath, 'utf8');

    // Use gray-matter to parse the post metadata section
    const matterResult = matter(fileContents);

    // Combine the data with the id
    return {
      id,
      ...matterResult.data,
    };
  });
  // Filter out draft posts
  const livePosts = allPostsData.filter((postData) => {
    return postData.draft == false
  })
  // Sort posts by date
  return livePosts.sort((a, b) => {
    if (a.date < b.date) {
      return 1;
    } else {
      return -1;
    }
  });
}

export async function getServerSideProps({ res }) {
  const posts = getSortedPostsData();

  // Generate the XML sitemap with the blog data
  const sitemap = generateSiteMap(posts);

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

  return {
    props: {},
  };
}

export default function SiteMap() {}
Enter fullscreen mode Exit fullscreen mode
  1. Run npm run dev locally to verify that the http://localhost:3000/sitemap.xml is created successfully.

That's it!

Conclusion

You can deploy your Next.js app and verify the sitemap with all 'posts' links dynamically generated for you without any additional effort.

Your website's sitemap should have the same structure as mine.

Here is how my sitemap looks → https://notionworkspaces.com/sitemap.xml

You can also modify the above code to add/delete parts that are unique to your blog.

I hope you found this useful!

👋 -- @TnvMadhav

Top comments (0)