Next.js Discord

Discord Forum

server actions in next-sitemap.config.js (or alternatives)?

Unanswered
Spectacled bear posted this in #help-forum
Open in Discord
Spectacled bearOP
I'm using the [next-sitemap package](https://www.npmjs.com/package/next-sitemap) to generate sitemaps dynamically.

Inside the next-sitemap.config.js I'd like to use the server actions of my next.js project to query the database and get the data for the different pages.

Unfortunately it didn't work for me yet because I'm constantly running into errors about the incompatibility between CommonJS and ES Modules.

Suggestions how to use server actions inside next-sitemap.config.js?
Or any better approach?

29 Replies

Spectacled bearOP
Probably you are right.
I remember have chosen the package because the documentation was intuitive and straight forward.
While next.js' generateSitemaps wasn't really well documented...

But maybe I'll give it another try
it works like generateStaticParams
Spectacled bearOP
So you defined it separately for each route?
depend on your site, we can just use app/sitemap.ts
a sitemap can have around 50000 item, you should use generateSitemaps if you have more than that
Spectacled bearOP
The important point for me is that I want to add the correct URL paths to the sitemap - not the "original" URLs but the one's which I created using a middleware.
But looks like this shouldn't be a problem with generateSitemaps
@Ray depend on your site, we can just use `app/sitemap.ts`
Spectacled bearOP
The actual challenge is getting all the pages for which you want to generate an entry in the sitemap.
Using the next-sitemap package that's easy, because it just gets all existing paths for you automatically.
Using the sitemap feature in next.js, I need a [different logic - e.g. based on DB entries](https://youtu.be/FukseskiIkE?t=1803).

When I generate thousands of static pages I find it more convenient to do something like this (based on next-sitemap package) to generate my sitemap:
module.exports = {
  transform: async (config, path) => {
    if (path.includes("/doc-in/")){
      let cityName = path.split("/doc-in/").at(-1);

      const slugPath = encodeURI(`doc-in-${cityName}`)

      return {
        loc: slugPath,
        alternateRefs: config.alternateRefs ?? [],  
      }
    }


...instead of coming up with a whole new logic.
Or is there a way to conveniently find and loop over all my SSG pages to generate a sitemap with all of them?
just query the data from database?
export default async function sitemap() {
  const cities = await db.city.findMany()

  return cities.map(city => ({
    url: `/doc-in-${city.name}`,
    lastModified: city.updatedAt
  }))
}
@Ray just query the data from database?
Spectacled bearOP
Yes, I'll have to do that.
It's just an extra step compared to the package.

Fortunately I've already added the required parts of the slug to the DB entries.
So it's not too much of an issue currently.

What's more bugging is that I [didn't find a good alternative to querying the database in middleware yet](https://nextjs-forum.com/post/1190593895155900437#message-1190593895155900437).
Spectacled bearOP
Is it possible to generate a sitemap index file which links to the "sub-sitemaps" in nextjs?
yes in app/sitemap.ts
Spectacled bearOP
So you would use app/sitemap.ts as index and then build sub-sitemaps inside the different routes?

Currently I'm doing it like this:
export default async function sitemap() {
    const allHpData = await getAllHpData()
    const uniqueCityNamesAndSlugs = await getUniqueCityNamesAndSlugs()

    // sitemap entries for city landing pages
    const cityUrls = uniqueCityNamesAndSlugs.map(citySlugNameObj => {
        return {
            url: `${siteUrl}/doc-in-${Object.keys(citySlugNameObj)[0]}`,
        }
    }) ?? [];
    
    
    // sitemap entries for HP detail pages
    const hpDetailUrls = allHpData.map(hp => {
        return {
            url: `${siteUrl}/doc-${hp.hpNameSlug}-in-${hp.hpCitySlug}`,
        }
    }) ?? [];


    return [
        {
            url: siteUrl,
        },
        ...cityUrls,
        ...hpDetailUrls,
    ]
}


What if I wanted to limit the number of entries to say 7000 per sitemap.
And for every 7000 entries in the sitemap I actually want to have a sub-sitemap.
Is that possible?
I think next will generate those for you? if you have
app/cities/sitemap.ts
app/hp/sitemap.ts
let me try
@Ray I think next will generate those for you? if you have `app/cities/sitemap.ts` `app/hp/sitemap.ts`
Spectacled bearOP
Possible.
So far I put all the logic inside a single app/sitemap.ts file
oh no it doesn't
I think we could use app/sitemap.ts as index
// app/sitemap.ts
export default async function sitemap() {
  return [ url: '/cities/sitemap.xml', url: '/hp/sitemap.xml' ]
}
Spectacled bearOP
But an index sitemap has a slightly different structure compared to "normal" sitemaps:
https://developers.google.com/search/docs/crawling-indexing/sitemaps/large-sitemaps
you could use app/sitemap.xml/route.ts instead of app/sitemap.ts if you want
then you have full control how the content look like
Spectacled bearOP
interesting approach🤔
I'll have to try a few things.
However, I actually like the simplicity and the way the next-sitemap package handles all this using best practices.
The only drawback is that I couldn't figure out how to query database in there
Spectacled bearOP
Okay, this is huge - if it works as I understand!
I'll have to try that.
Thanks a lot for the hint.
I saw this part before but didn't understand what it's actually about.😄