Generate a Sitemap in Next.js 13/14 - SEO Optimized Apps

One crucial aspect of creating a successful web application is search engine optimization (SEO), which ensures that your app is easily discoverable by search engines.

This article delves into generating a sitemap for Next.js in version 13 (version 13.4.5+, to be specific) or 14 applications.

This is an essential step towards quickly building and managing SEO-optimized web apps.

This guide will show you how to create a sitemap, statically using a sitemap.xml file and dynamically using sitemap.ts for TypeScript and sitemap.js for JavaScript.

What is a Sitemap?

A sitemap is an XML file that lists the URLs of a website along with additional metadata about each URL.

A sitemap is an XML file listing all the pages of your website you want to be found by search engines. It's like a roadmap for search engines to follow when they crawl your site.

Manual Sitemap Creation

Let's start with the hard way.

Building and managing your sitemap.xml file.

Create a sitemap.xml file in the /app directory of your Next.js project.

Here's an example of what this file might look like:

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://yourwebsite.com</loc>
    <lastmod>2023-04-06</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
   <url>
    <loc>https://yourwebsite.com/page1</loc>
    <lastmod>2023-04-06</lastmod>
    <changefreq>daily</changefreq>
    <priority>0.8</priority>
  </url>
   <!-- Add more URLs here -->
</urlset>

And as you can imagine, this can get very tiresome fast!

So, let's look at how you might generate this data.

Dynamic Sitemap Creation

You might want a dynamic sitemap if your site content changes often, like adding new articles.

Or if you are like most coders, want to automate everything...

First, look at how we might create a generated sitemap using static data in Next.js.

export default async function sitemap() {
  const articles = await fetchArticlesFromDatabase();
  return articles.map(article => ({
    url: `https://yoursite.com/blog/${article.slug}`,
    lastModified: article.updatedAt,
    changeFrequency: 'weekly',
    priority: 0.5
  }));
}

If you are running your development server, you test how this will behave while in development; you can visit http://localhost:3000/sitemap.xml to compile the file and see what it generates.

For completeness, here are the differences between the TypeScript and JavaScript implementations:

TypeScript Example (sitemap.ts):

import { MetadataRoute } from 'next'

export default function sitemap(): MetadataRoute.Sitemap {
  // Fetch your articles or other dynamic content here
  return [
    // Add your URLs dynamically
  ]
}

The Sitemap return type looks like this:

type Sitemap = Array<{
  url: string
  lastModified?: string | Date
  changeFrequency?:
    | 'always'
    | 'hourly'
    | 'daily'
    | 'weekly'
    | 'monthly'
    | 'yearly'
    | 'never'
  priority?: number
}>

JavaScript Example (sitemap.js):

The JavaScript version is the same just without type annotations.

export default function sitemap() {
  // Fetch your articles or other dynamic content here
  return [
    // Add your URLs dynamically
  ]
}
Step 2: Populate with Dynamic Content
For example, if you're fetching articles from a database:

Limitations for Dynamic Sitemaps

Although these options will be enough for 95% of people. There are a couple of things at the time of writing that using sitemap.ts or sitemap.js doesn't support:

  • Multiple sitemaps
  • Sitemap indexes

Understanding Sitemap Options

When creating a dynamic sitemap in Next.js, you'll encounter several key options. Understanding these is crucial for optimizing your sitemap for search engines:

url

This is the absolute URL of the page that you are including in the sitemap.

It tells search engines exactly where to find the page on your website.

Always use the full URL, including https.

lastModified

This indicates the date when the content of the URL was last updated.

It helps search engines understand how frequently the content at the URL changes, which can affect how often search engines crawl that page.

This can be a Date object or a string. Ensure it's in a format recognized by search engines, typically in the ISO 8601 format.

changeFrequency

This option suggests to search engines how often the content at the URL is likely to change.

While not always strictly adhered to by search engines, it provides a general guideline about the page's update frequency.

We can pass the following options: "always", "hourly", "daily", "weekly", "monthly", "yearly", and "never".

Choose a value that best matches the update frequency of the content.

priority

This value, between 0.0 and 1.0, indicates the relative importance of the URL in the context of the entire site.

It helps search engines prioritize crawling, although its influence is often considered marginal.

Assign higher values to the most important pages. However, use this carefully, as overemphasizing all pages can dilute the value of essential pages.


Now, I hope you have everything you need to create sitemaps for your apps! 📈

If you have questions, sign up for a free invite to the Codú community Discord, where you can ask our community questions.

Or, you can leave a comment below this post. 👇

SeoNextjs
Avatar for Niall Maher

Written by Niall Maher

Founder of Codú - The web developer community! I've worked in nearly every corner of technology businesses: Lead Developer, Software Architect, Product Manager, CTO, and now happily a Founder.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.