A quick and easy guide to creating a sitemap for a Next.js site
Tags: nextjs, javascript, webdev, programming
Published: 2023-06-13 13:23:59

If you're looking to generate sitemaps for your Next.js website, the `next-sitemap` [npm package](https://www.npmjs.com/package/next-sitemap) is a great tool to help you with that. In this tutorial, I'll guide you through the process of using this package and explain why you would want to use it.

## Why Use `next-sitemap`?

Sitemaps are essential for search engine optimization (SEO) as they help search engines discover and index the pages on your website. By using the `next-sitemap` package, you can easily generate sitemaps for your Next.js website, ensuring that search engines can crawl and index your pages effectively.

## Installation

To get started, you need to install the `next-sitemap` package. Open your terminal and run the following command:

```bash
yarn add next-sitemap
```

## Create a Config File

The `next-sitemap` package requires a basic config file named `next-sitemap.config.js` in the root directory of your project. This file will contain the configuration options for generating your sitemaps. Here's an example of a basic config file:

```javascript
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL || 'https://example.com',
  generateRobotsTxt: true, // (optional)
  // ...other options
};
```

Make sure to replace `'`[`https://example.com`](https://example.com)`'` with the base URL of your website. You can also customize other options as needed.

## Building Sitemaps

To build the sitemaps, you need to add a postbuild script in your `package.json` file. Open the `package.json` file and add the following script:

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

This script tells Next.js to run the `next-sitemap` command after the build process is complete.

## Custom Config File

If you want to use a custom config file instead of the default `next-sitemap.config.js`, you can specify it when running the build command. For example:

```json
{
  "build": "next build",
  "postbuild": "next-sitemap --config awesome.config.js"
}
```

This allows you to have different configuration files for different environments or purposes.

## Building Sitemaps with pnpm

If you're using the pnpm package manager, you need to create a `.npmrc` file in the root of your project to enable the postbuild step. Add the following line to the `.npmrc` file:

```text
enable-pre-post-scripts=true
```

This ensures that pnpm runs the postbuild script defined in your `package.json`.

## Index Sitemaps (Optional)

Starting from version 2.x of `next-sitemap`, the `sitemap.xml` file will be the Index Sitemap, which contains URLs of all other generated sitemap endpoints. If you have a small or hobby site that doesn't require an index sitemap, you can turn off index sitemap generation by setting `generateIndexSitemap: false` in your `next-sitemap` config file.

```javascript
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: 'https://example.com',
  generateRobotsTxt: true,
  generateIndexSitemap: false,
};
```

## Splitting Large Sitemap into Multiple Files

If your sitemap becomes too large, you can split it into multiple files for better organization. To do this, define the `sitemapSize` property in your `next-sitemap.config.js` file.

For example:

```javascript
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: 'https://example.com',
  generateRobotsTxt: true,
  sitemapSize: 7000,
};
```

In this example, when the number of URLs in a sitemap exceeds 7000, `next-sitemap` will create separate sitemap files (e.g., `sitemap-0.xml`, `sitemap-1.xml`) and an index file (e.g., `sitemap.xml`).

## Configuration Options

Here are the available configuration options that you can use in your `next-sitemap.config.js` file:

| Property | Description | Type |
| --- | --- | --- |
| `siteUrl` | Base URL of your website | string |
| `output` | Next.js output modes (check documentation) | string |
| `changefreq` | Change frequency of pages (default: daily) | string |
| `priority` | Priority of pages (default: 0.7) | number |
| `sitemapBaseFileName` | The name of the generated sitemap file before the file extension (default: "sitemap") | string |
| `alternateRefs` | Denote multi-language support by unique URL | AlternateRef\[\] |
| `sitemapSize` | Split large sitemap into multiple files by specifying sitemap size (default: 5000) | number |
| `autoLastmod` | Add the `<lastmod/>` property to the sitemap (default: true) | boolean |
| `exclude` | Array of relative paths (wildcard pattern supported) to exclude from the sitemap | string\[\] |
| `sourceDir` | Next.js build directory (default: ".next") | string |
| `outDir` | Directory where the generated files will be exported (default: "public") | string |
| `transform` | A transformation function that runs for each relative path in the sitemap | async function |
| `additionalPaths` | Async function that returns a list of additional paths to be added to the generated sitemap list | async function |
| `generateIndexSitemap` | Generate index sitemaps (default: true) | boolean |
| `generateRobotsTxt` | Generate a `robots.txt` file and list the generated sitemaps (default: false) | boolean |
| `robotsTxtOptions` | Options for generating the `robots.txt` file | object |

Please refer to the `next-sitemap` documentation for more details on each configuration option.

## Custom Transformation Function

The `transform` option allows you to define a custom transformation function that runs for each relative path in the sitemap. This function can add, remove, or exclude paths or properties from the URL set. Here's an example:

```javascript
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  transform: async (config, path) => {
    // Custom function to ignore the path
    if (customIgnoreFunction(path)) {
      return null;
    }

    // Only create changefreq along with path
    if (customLimitedField(path)) {
      return {
        loc: path,
        changefreq: 'weekly',
      };
    }

    // Use default transformation for all other cases
    return {
      loc: path,
      changefreq: config.changefreq,
      priority: config.priority,
      lastmod: config.autoLastmod ? new Date

().toISOString() : undefined,
      alternateRefs: config.alternateRefs ?? [],
    };
  },
};
```

In this example, the custom transformation function checks if a path should be ignored or if it requires a limited set of properties. It returns `null` to exclude a specific path or returns an object with properties for other cases.

## Additional Paths Function

The `additionalPaths` function allows you to dynamically add additional paths to the generated sitemap list. It is useful when you have a large list of pages but don't want to render them all. The function should return an array of objects, where each object represents an additional path. Here's an example:

```javascript
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  additionalPaths: async (config) => {
    const result = [];

    // Required value only
    result.push({ loc: '/additional-page-1' });

    // All possible values
    result.push({
      loc: '/additional-page-2',
      changefreq: 'yearly',
      priority: 0.7,
      lastmod: new Date().toISOString(),

      // Acts only on '/additional-page-2'
      alternateRefs: [
        {
          href: 'https://es.example.com',
          hreflang: 'es',
        },
        {
          href: 'https://fr.example.com',
          hreflang: 'fr',
        },
      ],
    });

    // Using transformation from the current configuration
    result.push(await config.transform(config, '/additional-page-3'));

    return result;
  },
};
```

In this example, the `additionalPaths` function adds three additional paths to the sitemap, each with different properties. You can customize this function based on your specific requirements.

## Full Configuration Example

Here's an example of a `next-sitemap.config.js` configuration file with all available options:

```javascript
/** @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',
    },
  ],
  transform: async (config, path) => {
    return {
      loc: 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',
    ],
  },
};
```

Feel free to adjust the values based on your specific needs.

## Generating Dynamic/Server-side Sitemaps

The `next-sitemap` package also provides APIs to generate server-side sitemaps. This is useful when you need to generate sitemaps dynamically from a content management system (CMS) or a custom data source.

There are two APIs available:

`getServerSideSitemapIndex`: Generates index sitemaps based on the provided URLs and returns an `application/xml` response. Supports Next.js route files (e.g., `route.ts`, `route.js`) starting from Next.js 13+.

`getServerSideSitemap`: Generates a sitemap based on field entries and returns an `application/xml` response. Supports Next.js route files (e.g., `route.ts`, `route.js`) starting from Next.js 13+.

To use these APIs, you can import them into your Next.js application and configure them according to your needs. For more information and examples, please refer to the `next-sitemap` documentation.

## Typescript JSDoc

If you're using TypeScript, you can enhance your development experience by adding the following line of code in your `next-sitemap.config.js` file:

```javascript
/** @type {import('next-sitemap').IConfig} */
module.exports = {
  // YOUR CONFIG
};
```

This line provides TypeScript autocomplete and type checking for the configuration options.

That's it! You're now equipped with the knowledge to use the `next-sitemap` npm package to generate sitemaps for your Next.js website. Happy coding and optimizing your website for search engines!

<iframe src="https://aimodels.substack.com/embed" width="100%" height="auto" style="box-sizing:border-box;border:0px;display:block;overflow:hidden;width:720px;grid-column:main-start / main-end;margin-bottom:0px;margin-top:calc(1.6em*var(--content-spacing-multiplier, 1));color:rgb(21, 23, 26);font-family:Inter, -apple-system, "system-ui", "Segoe UI", Helvetica, Arial, sans-serif;font-size:18px;font-style:normal;font-variant-ligatures:normal;font-variant-caps:normal;font-weight:400;letter-spacing:normal;orphans:2;text-align:start;text-indent:0px;text-transform:none;widows:2;word-spacing:0px;-webkit-text-stroke-width:0px;white-space:normal;background-color:rgb(255, 255, 255);text-decoration-thickness:initial;text-decoration-style:initial;text-decoration-color:initial"></iframe>

*Subscribe or follow me on* [*Twitter*](https://twitter.com/mikeyoung44) *for more content like this!*