Back to blog

Published on Monday, March 10, 2025

Next.js Sitemap Setup with next-sitemap

Next.js Sitemap Setup with next-sitemap

Introduction

next-sitemap is a powerful package designed to automate the generation of sitemaps and robots.txt files in Next.js projects. This guide covers installation, configuration, and advanced options to optimize your SEO efforts effectively.

Installation

To install next-sitemap, run the following command:

npm install next-sitemap

Creating the Configuration File

next-sitemap requires a configuration file named next-sitemap.config.js in your project's root directory.

next-sitemap.config.js
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL || 'https://example.com',
}

next-sitemap automatically loads environment variables from .env files.

Building Sitemaps

To generate sitemaps after building your project, update your package.json scripts:

{
  "build": "next build",
  "postbuild": "next-sitemap"
}

Custom Configuration File:

You can specify a custom configuration file using the --config flag:

{ "postbuild": "next-sitemap --config awesome.config.js" }

Using next-sitemap with PNPM

For PNPM users, create a .npmrc file in your project root with the following content:

.npmrc
enable-pre-post-scripts=true

Adding Additional Routes Manually

next-sitemap includes all routes by default, but you can use additionalPaths to add extra non-standard routes.

next-sitemap.config.js
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL,
  additionalPaths(config) {
    const routes = [
      "/blog/post-01",
      "/channels/codifyblog",
      "/users/codifyblog",
    ];
       
    return routes.map((route) => ({
      loc: `${config.siteUrl}${route}`,
       lastmod: new Date().toISOString(),
       changefreq: "daily",
       priority: 1,
    }));
  }
};

Adding Dynamic Routes

For dynamic routes like app/blog/[slug]/page.tsx, you can create a sitemap like this:

app/blog/sitemap.ts
import type { MetadataRoute } from "next";

type Post = {
  slug: string;
  updatedAt: Date;
}

async function getAllPosts(): Promise<Post[]> {
  return [
    {
       slug: "hello-world",
       updatedAt: new Date(),
    },
    {
      slug: "another-post",
      updatedAt: new Date(),
    },
  ];
}

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const BASE_URL = process.env.SITE_BASE_URL || "http://exanmple.com";
  const posts = await getAllPosts();

  return posts.map((post) => {
    return {
      url: `${BASE_URL}/blog/${post.slug}`,
      lastModified: post.updatedAt,
      changeFrequency: "daily",
      priority: 1.0,
    };
 });
}

Note:

To include the generated sitemap in your robots.txt, update your next-sitemap configuration like this:

next-sitemap.config.js
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  robotsTxtOptions: {
    additionalSitemaps: [
      `${process.env.SITE_URL}/blog/sitemap.xml`,
    ]
  }
};

Generating Robots.txt File

To generate a robots.txt file with custom rules and additional sitemaps, use the following configuration:

next-sitemap.config.js
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: 'https://example.com',
  generateRobotsTxt: true,
  robotsTxtOptions: {
    policies: [
      { userAgent: '*', allow: '/' },
      { userAgent: 'test-bot', allow: ['/path', '/path-2'] },
      { userAgent: 'black-listed-bot', disallow: ['/sub-path-1', '/path-2'] },
    ],
    additionalSitemaps: [
      'https://example.com/my-custom-sitemap-1.xml',
      'https://example.com/my-custom-sitemap-2.xml',
      'https://example.com/my-custom-sitemap-3.xml',
    ],
  },
};

Above configuration will generate sitemaps based on your project and a robots.txt like this.

public/robots.txt
# *
User-agent: *
Allow: /

# test-bot
User-agent: test-bot
Allow: /path
Allow: /path-2

# black-listed-bot
User-agent: black-listed-bot
Disallow: /sub-path-1
Disallow: /path-2

# Host
Host: https://example.com

# Sitemaps
Sitemap: https://example.com/sitemap.xml # Index sitemap
Sitemap: https://example.com/my-custom-sitemap-1.xml
Sitemap: https://example.com/my-custom-sitemap-2.xml
Sitemap: https://example.com/my-custom-sitemap-3.xml

Full configuration example

Here's an example next-sitemap.config.js configuration with all options

next-sitemap.config.js
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: 'https://example.com',
  changefreq: 'daily',
  priority: 0.7,
  sitemapSize: 5000,
  generateRobotsTxt: true,
  exclude: ['/protected-page', '/awesome/secret-page'],
  alternateRefs: [
    {
      href: 'https://es.example.com',
      hreflang: 'es',
    },
    {
      href: 'https://fr.example.com',
      hreflang: 'fr',
    },
  ],
  // Default transformation function
  transform: async (config, path) => {
    return {
      loc: path, // => this will be exported as http(s)://<config.siteUrl>/<path>
      changefreq: config.changefreq,
      priority: config.priority,
      lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
      alternateRefs: config.alternateRefs ?? [],
    }
  },
  additionalPaths: async (config) => [
    await config.transform(config, '/additional-page'),
  ],
  robotsTxtOptions: {
    policies: [
      {
        userAgent: '*',
        allow: '/',
      },
      {
        userAgent: 'test-bot',
        allow: ['/path', '/path-2'],
      },
      {
        userAgent: 'black-listed-bot',
        disallow: ['/sub-path-1', '/path-2'],
      },
    ],
    additionalSitemaps: [
      'https://example.com/my-custom-sitemap-1.xml',
      'https://example.com/my-custom-sitemap-2.xml',
      'https://example.com/my-custom-sitemap-3.xml',
    ],
  },
}

Ignore Generated Sitemap Files

To prevent committing generated sitemaps and robots.txt files, add the following lines to your .gitignore file:

.gitignore
# generated sitemaps (next-sitemap)
public/robots.txt
public/sitemap*.xml

This ensures your generated files are excluded from version control.

Conclusion

The next-sitemap package simplifies sitemap generation and enhances your site's SEO performance. With flexible options for customization, it's a must-have for any Next.js project aiming to improve search engine visibility.