@reecem/prismic-sitemap

Sitemap Generator for Prismic and Next.js with Minimal Configuration


Keywords
javascript, nextjs, prismic.io, sitemap, sitemap generator, prismicio
License
MIT
Install
npm install @reecem/prismic-sitemap@0.5.3

Documentation

Prismic Sitemap Generator

Node.js CI Package Deploy GitHub license npm npm

An easy to configure sitemap generator for Next.js websites based on the pages in your Prismic.io CMS.

About

This package uses the Sitemap.js package to generate the sitemaps as it handles all the needed stuff for sitemaps. This also gives the end user flexibility in generating the sitemap.

It aims to simplify the configuration required to create the sitemap, and also include it in the build process of your Next.js site by extending the next.config.js file.

This package is also inspired by the live steam from Prismic.io where they built a sitemap generator. But wanting to make it better like.

Installation

You can use either npm or yarn to install the package:

NPM

npm install --save-dev @reecem/prismic-sitemap

Yarn

yarn add -D @reecem/prismic-sitemap

Usage

The package is configured and used inside the next.config.js file.

It works in a similar way to most Next.js plugins, it will also call the top-level webpack() function in the next.config.js file.

Basic usage

A basic Next.js file that has the sitemap generator plugin running would like as follows:

// The Prismic API endpoint
const API_ENDPOINT = `https://${process.env.REPOSITORY_NAME}.cdn.prismic.io/api/v2`;

// The hostname of the website, for example it would be https://example.com
const SITE_URL = process.env.VERCEL_ENV;

// this is the link resolver for the documents that are fetched.
const linkResolver = doc => {
  
  if (doc.type == 'post') {
    return `blog/${doc.uid}`;
  } 

  return `${doc.uid}`;
};

const withPrismicSitemap = require('@reecem/prismic-sitemap')({
  linkResolver: linkResolver,
  apiEndpoint: API_ENDPOINT,
  hostname: SITE_URL,
  optionsMapPerDocumentType: {
    // setting the update date of the article.
    post: (document) => {
      return { 
        // get the last time the document was published in Prismic
        lastmod: document.last_publication_date,
        changefreq: "weekly", 
        priority: 0.8 
      }
    }
    page: { changefreq: "monthly", priority: 1 }
  },
  documentTypes: ['page', 'post']
});

module.exports = withPrismicSitemap({
    ... other nextConfig things here... or before :)
})

Multiple Page usage / Multilang too

A more complex example would be to have multiple page types and also multi-language support inside the sitemap.

This one will use a linkResolver that picks if it should use the default local pattern or the localized version and sets that as a prefix.

// The Prismic API endpoint
const API_ENDPOINT = `https://${process.env.REPOSITORY_NAME}.cdn.prismic.io/api/v2`;

// The hostname of the website, for example it would be https://example.com
const SITE_URL = process.env.VERCEL_ENV;

const linkResolver = doc => {
  const prefix = doc.lang !== "en-za" ? `/${doc.lang}` : "";

  switch (doc.type) {
    case "homepage":
    case "pricing":
    case "page":
      return `${prefix}/${doc.uid ? doc.uid : ''}`;

    case "post":
      return `${prefix}/blog/${doc.uid}`;

    case "legal":
      return `${prefix}/legal/${doc.uid}`;

    case "product":
      return `${prefix}/product/${doc.uid}`;

    default:
      throw new Error(`Unknown doc.type: "${doc.type}"`);
  }
};

const withPrismicSitemap = require('@reecem/prismic-sitemap')({
    linkResolver: linkResolver,
    apiEndpoint: API_ENDPOINT,
    hostname: SITE_URL,
    optionsMapPerDocumentType: {
      page: { changefreq: "monthly", priority: 1 },
      // homepage: { changefreq: "monthly", priority: 1 }, Homepage would default to this as it isn't found
      // legal: { changefreq: "monthly", priority: 1 }, Legal types would default to this as it isn't found
      post: { changefreq: "weekly", priority: 0.8 },
      pricing: { changefreq: "monthly", priority: 1 }
    },
  documentTypes: ['homepage', 'page', 'pricing', 'legal']
})

module.exports = withPrismicSitemap({
    ... other nextConfig things here... or before :)
})

Private Prismic Repo Usage

If you are using a closed or private prismic repository, you may need to use the API token to get published documents. From version 0.2.0 you can add the token.

Below is an example, you need to add the sitemap.accessToken to the config.

// The Prismic API endpoint
const API_ENDPOINT = `https://${process.env.REPOSITORY_NAME}.cdn.prismic.io/api/v2`;

// The hostname of the website, for example it would be https://example.com
const SITE_URL = process.env.VERCEL_ENV;

// this is the link resolver for the documents that are fetched.
const linkResolver = doc => {
  
  if (doc.type == 'post') {
    return `blog/${doc.uid}`;
  } 

  return `${doc.uid}`;
};

const withPrismicSitemap = require('@reecem/prismic-sitemap')(sitemap: {
  linkResolver: linkResolver,
  apiEndpoint: API_ENDPOINT,
  accessToken: process.env.PRISMIC_ACCESS_TOKEN,
  hostname: SITE_URL,
  optionsMapPerDocumentType: {
      post: { changefreq: "weekly", priority: 0.8 },
      page: { changefreq: "monthly", priority: 1 }
  },
  documentTypes: ['page', 'post']
})

module.exports = withPrismicSitemap({
    ... other nextConfig things here..
})

<lastmod> support

The package makes use of lastmod support for the sitemap, this would need to be set by the user if you would want the date to come through at the current version of 0.3.0.

Because the Sitemap file is written using a separate package, it supports parsing the date straight to the YYYY-MM-DD format, if you would like it to have the time as well, you will need to override the setting in the config:

  sitemap: {

    sitemapConfig: {
      lastmodDateOnly: false,
    },

  }

API

The sitemap object is made up of the following:

{
  sitemap: {
    linkResolver = Function,
    apiEndpoint = String,
    accessToken = String|null,
    hostname = String,
    fileName = String,
    optionsMapPerDocumentType = Object|Object<Function>,
    defaultEntryOption = Object,
    staticPaths = Array<Object>,
    pagination = {
      pageSize: Number,
    },
    documentTypes = Array,
    sitemapConfig = Object
  }
}
Option Type eg Description
linkResolver function doc => {return `/path/${doc.uid}`;} This is the Prismic.io link resolver, this could be custom, or used from the prismic-configuration files.
apiEndpoint string 'https://some-repository-on-prismic.cdn.prismic.io/api/v2' This is the URL of your Prismic repository, the API version of it.
accessToken string(optional) 'random_api_string_that_you_get' This is the Access token used to access private Prismic Repositories
hostname string 'http://example.com/' The hostname of your Vercel/Next.js application
fileName string 'sitemap.xml' The name of the sitemap, it is always placed inside public
optionsMapPerDocumentType object { page: { changefreq: "monthly", priority: 1 }, post: (doc) => {lastmod: doc.last_publication_date}} The options for the documents that are indexed, this can also have other options, found at https://github.com/ekalinin/sitemap.js/blob/master/api.md#sitemap-item-options
documentTypes array ['homepage', 'page', 'pricing', 'legal']
defaultEntryOption object (optional) { changefreq: "monthly", priority: 1, } This is the default to add when nothing exists for the type or callback for entries
staticPaths array [{ url: '/static/path', changefreq: "yearly", priority: 1, lastmod: '2000-01-01'}] Use this if you would like to define a custom path for the Sitemap that doesn't come from the CMS
pagination.pageSize number {pagination: {pageSize: 30}} This sets the number of pages per request on the automatic pagination. Defaults to 20 per request
sitemapConfig object see https://github.com/ekalinin/sitemap.js#options-you-can-pass

optionsMapPerDocumentType

The optionsMapPerDocumentType setting for the sitemap value allows you to configure the object result for the sitemap entry for the specific document

This accepts a object with keys to the document type from Prismic, the value can be a object, or a callback.

Using the Callback

This option allows you to determine extra data about the document and return a object to be written to the Sitemap, there isn't a need to return the URL value, and this will be purged from the result anyway in favour of the linkResolver result. This is for consistency reasons.

The primary reason to add this is because of using the <lastmod> XML attribute in the Sitemap to improve indexing by Google or other search engines.

To make use of this, you can do the following logic:

const withPrismicSitemap = require('@reecem/prismic-sitemap')({
  sitemap: {
    // ... other cofing
    optionsMapPerDocumentType: {
      post: (document) => {
        return {
          lastmod: document.last_publication_date ? document.last_publication_date : (new Date()).toJSON(),
          changefreq: 'monthly'
        };
      }
    },
  }
})

Testing

npm run test
yarn test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.