Lewis Tyler

Using getStaticPaths with WordPress in Next.js

Here’s how to get a list of all slugs (paths) for any Post Type via the WordPress API.

This useful when working with a Static Site Generator (SSG) that requires a list of paths to be collected and spun into static pages.

You’d think this would be straightforward, but WP API puts a hard limit on the number of posts you can request by default. If you’re dealing with a WordPress installation with a lot of content, it makes sense to paginate and concatenate;

// lib/api/wp.js

const axios = require("axios");
const API_URL = process.env.WORDPRESS_API_URL; // https://example.com/wp-json/wp-json/wp/v2

export const getAllPostSlugs = (postType = "posts") => {
  return new Promise((resolve, reject) => {
    const state = {
      posts: [],
      baseUrl: `${API_URL}/${postType}?status='publish'`,
      perPage: "&per_page=10",
      wpFetchHeaders: {
        headers: {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Expose-Headers": "x-wp-total",
        },
      },
    };

    async function getNumPosts() {
      const { headers } = await axios(
        `${state.baseUrl}${state.perPage}`,
        state.wpFetchHeaders
      );
      return headers["x-wp-totalpages"];
    }

    async function fetchPosts(numPages) {
      const posts = [];

      for (let page = 1; page <= numPages; page += 1) {
        const post = axios.get(
          `${state.baseUrl}${state.perPage}&page=${page}`,
          state.wpFetchHeaders
        );
        posts.push(post);
      }

      await axios
        .all(posts)
        .then((response) => {
          const postData = response.map((res) => res.data);
          const postsArr = postData.flat();

          postsArr.map((post) => {
            state.posts.push(post.slug);
          });
        })
        .catch((e) => reject(new Error(e)));
      return true;
    }

    getNumPosts()
      .then((numPosts) => fetchPosts(numPosts))
      .then(() => {
        resolve(state.posts);
      })
      .catch((e) => reject(new Error(e));
  });
};

Next.js static and WordPress

Next.js uses the getStaticPaths() function to get this list of static paths, so we can simply add our getAllPostSlugs() function from above (example below) to that.

that can be used to fetch every page for static generation in getStaticProps().

Here’s how it all comes together in Next.js:

// posts/[slug].js

import React from 'react';
import { getAllPostSlugs, getPost } from '../lib/api/wp';

const Post = ({ postData }) => {
  return (
    <>
      <h1>{postData.title.rendered}</h1>
      <div
        className="content"
         dangerouslySetInnerHTML={{__html: postData.content.rendered}} 
      />
    </>
  )
}

export async function getStaticProps( {params} ) {
	const postData = await getPostData(`/posts/${params.slug}`) // simple function to collect post content via URL like https://example.com/wp-json/wp/v2/posts?slug=${slug}

	return {
		props: { postData }
	};
}

export async function getStaticPaths() {
  const allPosts = await getAllPostSlugs('posts') // Supply your desired post type here
	const paths = allPosts.map((post) => ({
		params: { slug: post }
	}))

  return {
    paths,
    fallback: true,
  }
}

export default Posts;

Note: for Custom Post Types be sure to specify show_in_rest:

// cpt-books.php

$args = array(
  'show_in_rest'       => true,
  'rest_base'          => 'books',
);

register_post_type( 'book', $args );

Final thoughts

WordPress has become a dirty word amongst developers.

Its bad reputation is not unwarranted, either. There is indeed a litany of issues with WordPress, with security being top of the list.

But the reality is WordPress is a good CMS. The UI makes sense allows users a lot of control. It’s also widespread, so it’s not uncommon to come across projects with a lot of content inside WP.

While you could export and import the content into a fancy SaaS CMS, there isn’t much benefit in that, in my opinion.

The common corporate website built in WordPress is a good candidate for static conversion. With Next.js or similar, you can offer the comfort of WP with the speed and security of static.