Next-sitemap doesn't add sitemap.xml in .next (deploy folder) after updating to next 15rc

Hello everyone,

I’m have been scratching my head for 2 days, I went through a massive next update to 15rc + switch from commonJs to ESM.

Last error is to be able to build a nextjs 15rc application (works fine) and add the sitemap.xml from library next-sitemap.
It was working fine before updating to nextjs 15rc, but it somehow not work after updating.

Build is OK, no error thrown on build and on next-sitemap generation

3:12:33 PM: Netlify Build                                                 
3:12:33 PM: ────────────────────────────────────────────────────────────────
3:12:33 PM: ​
3:12:33 PM: ❯ Version
3:12:33 PM:   @netlify/build 29.56.1
3:12:33 PM: ​
3:12:33 PM: ❯ Flags
3:12:33 PM:   accountId: 63b947ba70c532716df3f613
3:12:33 PM:   baseRelDir: true
3:12:33 PM:   buildId: 6755a8fcbb70110008d3b8a2
3:12:33 PM:   deployId: 6755a8fcbb70110008d3b8a4
3:12:33 PM: ​
3:12:33 PM: ❯ Current directory
3:12:33 PM:   /opt/build/repo
3:12:33 PM: ​
3:12:33 PM: ❯ Config file
3:12:33 PM:   /opt/build/repo/netlify.toml
3:12:33 PM: ​
3:12:33 PM: ❯ Context
3:12:33 PM:   branch-deploy
3:12:33 PM: ​
3:12:33 PM: ❯ Using Next.js Runtime - v5.8.1
3:12:35 PM: Next.js cache restored
3:12:35 PM: ​
3:12:35 PM: Build command from Netlify app                                
3:12:35 PM: ────────────────────────────────────────────────────────────────
3:12:35 PM: ​
3:12:35 PM: $ yarn run build:stg
3:12:35 PM: yarn run v1.22.19
3:12:35 PM: $ env-cmd -f ./apps/front/.env.stg nx run front:build:stg && nx run front:sitemap:stg 
3:12:38 PM: > nx run front:build:stg
3:12:40 PM:    ▲ Next.js 15.0.3
3:12:40 PM:    - Environments: .env
3:12:40 PM:    Skipping linting
3:12:40 PM:    Checking validity of types ...
3:12:47 PM:    Creating an optimized production build ...
3:12:51 PM:  ✓ Compiled successfully
3:12:51 PM:    Collecting page data ...
3:12:55 PM:    Generating static pages (0/50) ...
3:12:57 PM:    Generating static pages (12/50)
3:12:58 PM:    Generating static pages (24/50)
3:12:58 PM:    Generating static pages (37/50)
3:12:58 PM:  ✓ Generating static pages (50/50)
3:13:20 PM:    Finalizing page optimization ...
3:13:20 PM:    Collecting build traces ...
3:13:28 PM: Route (pages)                                                                                                     Size     First Load JS
3:13:28 PM: ┌ ● /                                                                                                             6.68 kB         201 kB
3:13:28 PM: ├   └ css/da3afaaf73d2fd04.css                                                                                    1.09 kB
3:13:28 PM: ├   /_app                                                                                                         0 B             132 kB
3:13:28 PM: ├ ○ /404                                                                                                          3.54 kB         166 kB
3:13:28 PM: ├ ● /500                                                                                                          3.51 kB         166 kB
3:13:28 PM: ├ ● /blog                                                                                                         4.13 kB         166 kB
3:13:28 PM: ├   └ css/2720144f05a86372.css        
3:13:28 PM: ├ ● /docs                                                                                                         1.98 kB         164 kB
3:13:28 PM: ├ ● /docs/[...slug] (15439 ms)                                                                                    1.02 MB         1.2 MB
3:13:28 PM: ├   └ css/cd40b90687f00058.css             
3:13:28 PM: ├   ├ /en/docs/installation (1586 ms)
3:13:28 PM: ├   ├ /fr/docs/installation (1586 ms)
3:13:28 PM: ├   ├ /en/docs/providers/list-of-functions (1586 ms)
3:13:28 PM: ├   ├ /fr/docs/providers/list-of-functions (1586 ms)
3:13:28 PM: ├   ├ /en/docs/set-up-binance-api-key (1586 ms)
3:13:28 PM: ├   ├ /fr/docs/set-up-binance-api-key (1585 ms)
3:13:28 PM: ├   └ [+17 more paths]
3:13:28 PM: ├ ● /legal/[slug] (4622 ms)                                                                                       9.11 kB         204 kB
3:13:28 PM: ├   ├ /en/legal/cookie (773 ms)
3:13:28 PM: ├   ├ /fr/legal/cookie (770 ms)
3:13:28 PM: ├   ├ /en/legal/privacy (770 ms)
3:13:28 PM: ├   ├ /fr/legal/privacy (770 ms)
3:13:28 PM: ├   ├ /en/legal/term (770 ms)
3:13:28 PM: ├   └ /fr/legal/term (769 ms)
3:13:28 PM: └ ● /pricing                                                                                                      4.52 kB         167 kB
3:13:28 PM:     └ css/f8b1eadaaa79cc61.css                                                                                    913 B
3:13:28 PM: + First Load JS shared by all                                                                                     167 kB
3:13:28 PM:   ├ chunks/framework-b34def526800d0ea.js                                                                          57.5 kB
3:13:28 PM:   ├ chunks/main-3edc4c227945276a.js                                                                               33.9 kB
3:13:28 PM:   ├ chunks/pages/_app-cd377b53198a9e7b.js                                                                         40 kB
3:13:28 PM:   ├ css/78e51ce34dc62636.css                                                                                      34.3 kB
3:13:28 PM:   └ other shared chunks (total)                                                                                   984 B
3:13:28 PM: ○  (Static)  prerendered as static content
3:13:28 PM: ●  (SSG)     prerendered as static HTML (uses getStaticProps)
3:13:28 PM:  NX   Successfully ran target build for project front
3:13:29 PM: > nx run front:sitemap:stg
3:13:29 PM: > env-cmd -f ./apps/front/.env.stg  nx run front:sitemap
3:13:29 PM: > nx run front:sitemap
3:13:29 PM: > next-sitemap --config apps/front/next-sitemap.config.js
3:13:30 PM: ✨ [next-sitemap] Loading next-sitemap config: file:///opt/build/repo/apps/front/next-sitemap.config.js
3:13:30 PM: ✅ [next-sitemap] Generation completed
3:13:30 PM: ┌───────────────┬────────┐
3:13:30 PM: │    (index)    │ Values │
3:13:30 PM: ├───────────────┼────────┤
3:13:30 PM: │ indexSitemaps │   1    │
3:13:30 PM: │   sitemaps    │   1    │
3:13:30 PM: └───────────────┴────────┘
3:13:30 PM: -----------------------------------------------------
3:13:30 PM:  SITEMAP INDICES
3:13:30 PM: -----------------------------------------------------
3:13:30 PM:    ○ https://stg.linkyflow.com/sitemap.xml
3:13:30 PM: -----------------------------------------------------
3:13:30 PM:  SITEMAPS
3:13:30 PM: -----------------------------------------------------
3:13:30 PM:    ○ https://stg.linkyflow.com/sitemap-0.xml
3:13:30 PM:  NX   Successfully ran target sitemap for project front
3:13:30 PM:  NX   Successfully ran target sitemap for project front
3:13:30 PM: Done in 55.08s.
3:13:30 PM: ​
3:13:30 PM: (build.command completed in 55.2s)
3:13:32 PM: Next.js cache saved
3:13:32 PM: Next.js cache saved
3:13:34 PM: ​
3:13:34 PM: Functions bundling                                            
3:13:34 PM: ────────────────────────────────────────────────────────────────
3:13:34 PM: ​
3:13:34 PM: Packaging Functions from .netlify/functions-internal directory:
3:13:34 PM:  - ___netlify-server-handler/___netlify-server-handler.mjs
3:13:34 PM: ​
3:13:39 PM: ​
3:13:39 PM: (Functions bundling completed in 5.1s)
3:13:40 PM: ​
3:14:05 PM: (Netlify Build completed in 1m 31.9s)
3:14:06 PM: Section completed: building

But when I look at the deploy directory (below the build), we cannot see the sitemap.xml.


When I look to previous build (next 13), the sitemap.xml file was present.

When I build locally, build is successful, sitemap.xml is correctly added to .next folder.

next-sitemap.config.js is

/* eslint-disable @typescript-eslint/no-var-requires */
import fs from 'fs';
import graymatter from 'gray-matter';
const BLOG_CONTENT_DIR = './apps/front/content/blogs';
const allBlogFilePaths = fs.readdirSync(BLOG_CONTENT_DIR);

/** @type {import('next-sitemap').IConfig} */
export default {
  siteUrl: process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:4200',
  generateRobotsTxt: true,
  sourceDir: './dist/apps/front/.next',
  outDir: './dist/apps/front/.next',
  robotsTxtOptions: {
    policies: [
      {
        userAgent: '*',
        allow: process.env.NODE_ENV === 'production' ? '/' : '',
        disallow: process.env.NODE_ENV === 'production' ? '' : '/',
      },
    ],
  },

  transform: async (config, path) => {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const [_nothing, maybeLocale, ...rest] = path.split('/');

    let locale = 'en';
    let pathWithoutLocale;
    if (['fr'].includes(maybeLocale)) {
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      locale = maybeLocale;
      pathWithoutLocale = [...rest].join('/');
    } else {
      pathWithoutLocale = [maybeLocale, ...rest].join('/');
    }

    let alternateRefs = [
      {
        href: `${process.env.NEXT_PUBLIC_SITE_URL}${pathWithoutLocale ? `/${pathWithoutLocale}` : ''}`,
        hreflang: 'en',
        hrefIsAbsolute: true,
      },
      {
        href: `${process.env.NEXT_PUBLIC_SITE_URL}/fr${pathWithoutLocale ? `/${pathWithoutLocale}` : ''}`,
        hreflang: 'fr',
        hrefIsAbsolute: true,
      },
    ];

    const isBlogPost = path.includes('/blog/');
    if (isBlogPost) {
      const urlSplitted = path.split('/');
      const blogPath = urlSplitted[urlSplitted.length - 1];
      const idSlug = blogPath.split('-')[0];
      const currentBlogFilePath = allBlogFilePaths.find((f) => f.split('-')[0] === idSlug);
      const { data } = graymatter.read(`${BLOG_CONTENT_DIR}/${currentBlogFilePath}`, {
        language: 'yaml',
      });
      alternateRefs = [];
      for (const [key, value] of Object.entries(data)) {
        alternateRefs.push({
          href: `${process.env.NEXT_PUBLIC_SITE_URL}${key !== 'en' ? '/' + key : ''}/blog/${value.slug}`,
          hreflang: key,
          hrefIsAbsolute: true,
        });
      }
    }
    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,
    };
  },
  exclude: ['**/me*', '**/auth*', '**/legal*', '**/app*', '**/success', '**/404', '**/500'],
};

and netlify.toml is :

[[plugins]]
  package = "@netlify/plugin-nextjs"

(not much here because i set the publish directory directly in netlify UI because of monorepo and stuff)

I really have no idea why it is not added in the ./dist/apps/front/.next folder, or if it is added and netlify somehow skip it.

Any help or direction would be greatly appreciated.
Thanks !

Have you tried using --skipNxCache flag to ensure Nx cache is not acting up?

Just tried to update my build function to

env-cmd -f ./apps/front/.env.stg nx run front:build:stg  --skipNxCache && nx run front:sitemap:stg --skipNxCache

And even tried to clear netlify cache, but no luck :frowning:

I don’t see anything wrong with the setup. Could you share your repo?

Hi Hrishikesh, thanks for the reply.
Do you mean the github repo ? It’s a private repo and there is a loooot of stuff inside.

I uploaded a zip with the “front” package (just without the .env files)
front.zip (148.1 KB)
Note that it’s located in a nrwl monorepo located at “apps/front”.

thanks for the help.

The repo that you’ve shared doesn’t have a package.json, so I can’t test it myself. If you don’t mind sending over the complete repo, that could be useful. Of it you can reproduce this issue in an isolated minimal setup, that would be the best.