DEV Community

Cover image for Using WordPress as a headless CMS with Next.js

Using WordPress as a headless CMS with Next.js

Rob Kendal {{☕}} on September 13, 2020

In part one of using WordPress as a headless CMS with Next.js, we looked at the basics of setting up a WordPress instance so that we can access P...
Collapse
 
spencersmb profile image
spencer

This write up is super detailed and an awesome source of info thanks for sharing. I have one basic question. When I want to publish a new post or page from Wordpress, normally I just hit publish and it would show up when I refresh the blog posts index page on my server based wordpress site. What happens with next.js? What would I need to do in order to publish posts weekly using the Wordpress scheduler for example? Would the new post just show up in next.js when I hit refresh? I'm guessing not since its statically built.

Thanks again,
Spencer

Collapse
 
imakethesites profile image
Mark Wlodawski

Have you solved this yet? I need to publish more posts without touching my Next app.

Collapse
 
spencersmb profile image
spencer

I've only read that you can have wordpress fire a webhook that will tell Next.js to rebuild when you publish a new post. I read that from a post that was about a year old, so maybe there is a newer more streamlined way.

Thread Thread
 
imakethesites profile image
Mark Wlodawski

Dang, this might've been important to make note of in the article. Clearly I'm not an active blogger, as I built and published my blog a couple of months ago and I'm just now getting around to asking this, but I guess it's a learning experience.

Thread Thread
 
spencersmb profile image
spencer • Edited

Yea after reading @AndrewRoss comment below, It sounds like the future proof solution to git/webhooks. I would have a look through that.

Thread Thread
 
imakethesites profile image
Mark Wlodawski

Thanks, I'll check it out.

Thread Thread
 
logantai24 profile image
Logan Tai

If you are hosting your NextJS site in vercel/netlify, the incremental static generation feature should be able to facilitate your needs as the page will be built again in the background when a new request comes in, you only need to add a simple " revalidate: 1" in your getStaticProps function

nextjs.org/docs/basic-features/dat...

Thread Thread
 
imakethesites profile image
Mark Wlodawski

I am hosting on netlify, and I've been hoping there would be a faster solution than adding Apollo. I'll check this out, thanks.

Thread Thread
 
imakethesites profile image
Mark Wlodawski

@logantai24 Thanks, it worked!

Collapse
 
samuelkobe profile image
Samuel Kobe • Edited

Hello, thank you for writing such a detailed Article. I am having trouble getting up and running after adding the new directories and files above. When trying to view the posts on the /blog page at the step titled 'Checking the output' I am getting the following error after following the "blog articles page" link.

Screenshot: dev-to-uploads.s3.amazonaws.com/i/...

EDIT1:

I was able to get it working buy adding

export default Blog
Enter fullscreen mode Exit fullscreen mode

before

export async function getStaticProps() {
  const allPosts = await getAllPosts();
  return {
    props: {
      allPosts
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

Is this correct?

Collapse
 
setoelkahfi profile image
Seto

This is correct.

Collapse
 
imakethesites profile image
Mark Wlodawski

Thanks for this article, I've learned quite a bit!

Here are some details that might have seemed obvious to most people, but took work and mysterious errors for me to figure out:

  1. After editing your .env file by entering the WP URL, if your localhost had been running, close and restart it. Otherwise, you'll receive an error saying that actual URLs must be entered.
  2. After entering your GraphQL query into api.js, don't be surprised when you see an error saying that thumbnail can't return null from blog/index.js if you haven't populated each of the queried fields (author excerpt and thumbnail image) inside your post screen on the WordPress site.

Both of these were because I was using my own WordPress instance, maybe people who were using your information while following along didn't receive the errors.

Thanks again!

Collapse
 
trahulsam1997 profile image
Rahul

Thanks for this mate! I actually had the issue with the 2nd point.

Collapse
 
asross311 profile image
Andrew Ross

Great article Rob! I've been using Headless Wordpress for a couple of months now and thought I should mention that one of my absolute favorite features is stable "revalidate" on getStaticProps. Background incremental static regeneration is a game changer, seamlessly threading the headless WP server with the client in production. No githooks required

// ...
export const getStaticProps = async ({
    preview = false,
    // context,
    field = MODIFIED || TITLE || DATE,
    order = ASC || DESC,
    desiredCategory
}: StaticProps) => {
    // console.log(context);
    const allPosts = await getAllPostsForHomeAlphabetical({
        preview,
        field,
        order
    });
    const tagsAndPosts = await getTagAndPosts();
    const categories = await getCategories();

    // const apolloClient: ApolloClient<NormalizedCacheObject> = initializeApollo();

    // await apolloClient.query({
    //  query: ALL_POSTS_QUERY,
    //  variables: allPostsQueryVars
    // });
    // const userOptions = await getAllPostsForHomeSorted(preview, field);
    // IMPORTANT https://nextjs.org/blog/next-9-5#stable-incremental-static-regeneration
    return {
        props: {
            // initialApolloState: apolloClient.cache.extract(),
            allPosts,
            preview,
            tagsAndPosts,
            field,
            order,
            categories
        },
        revalidate: 1
    };
};

// ...
Enter fullscreen mode Exit fullscreen mode

(transitioning to @apollo/client is a work in progress)

nextjs.org/blog/next-9-5#stable-in...

Collapse
 
kendalmintcode profile image
Rob Kendal {{☕}}

Thanks Andrew and so pleased you like the article. Yes, thanks for highlighting this. It's a feature that's definitely worth people checking out as it is indeed a game changer.

Collapse
 
lowbin profile image
lowbin • Edited

First of all, thank you for this wonderful tutorial. I did my local installation connected to a wordpress installed on my server at Godaddy. When calling the blog page displays the error that is in the print.
I had a similar error in WP-headless with Gatsby locally did not display the Single Posts, but when I deployed on Netilify the posts were called.
Can you help me please?

Erro:
);
45 |

46 | export async function getAllPosts(preview) {
| ^
47 | const data = await fetchAPI(
48 | `
49 | query AllPosts {

Collapse
 
pasqat profile image
Pasquale

Great series to fast test WPgraphql and Nextjs. I have just one question.
Is there a way manipulate data set with dangerouslySetInnerHtml?

For expamle in the article is present a slider of image, on Next that slider will not be rendered properly (the gallery of gutemberg editor is show as a simple list)...

Collapse
 
lowbin profile image
lowbin • Edited

First of all, thank you for this wonderful tutorial. I did my local installation connected to a wordpress installed on my server at Godaddy. When calling the blog page displays the error that is in the print.
I had a similar error in WP-headless with Gatsby locally did not display the Single Posts, but when I deployed on Netilify the posts were called.
Can you help me please?

Collapse
 
zackrosegithub profile image
Zack Rose

Hi there,

when I go to my site/graphql I get the following error:

GraphQL Request must include at least one of those two parameters: \"query\" or \"queryId

Does anyone know why? I can't really go any further until I can access the data!

Thank you

Collapse
 
brentonjackson profile image
Brenton

Do it like this:

{sitename.com}/graphql?query={stuff that's in your graphiql query}

For example, to get all posts of a specific category:
query={category(id: "asdfh3e2"){posts{nodes{title}}}}

Play around with the GraphiQL IDE to find out the queries that go inside /graphql?query={}

Collapse
 
justintrang profile image
Justin Trang

I had same error before because I use GET in stead of POST.
If you use POST, then you should recheck your query string ( must start with: query ... )

Collapse
 
a007mr profile image
a007mr

Outstanding article! Thank you so much Rob for this detailed guide.

I did everything according to you blog and it works great on the local machine. I can read articles. However, I have a problem when I deploy it to vercel. It shows an error during the build time:

> Build error occurred
TypeError: Only absolute URLs are supported
    at getNodeRequestOptions (/vercel/path0/node_modules/next/dist/compiled/node-fetch/index.js:1:63538)
    at /vercel/path0/node_modules/next/dist/compiled/node-fetch/index.js:1:65069
    at new Promise (<anonymous>)
    at Function.fetch [as default] (/vercel/path0/node_modules/next/dist/compiled/node-fetch/index.js:1:65003)
    at fetchWithAgent (/vercel/path0/node_modules/next/dist/server/node-polyfill-fetch.js:53:39)
    at fetchAPI (/vercel/path0/.next/server/chunks/963.js:69:23)
    at getAllPostsWithSlug (/vercel/path0/.next/server/chunks/963.js:141:24)
    at getStaticPaths (/vercel/path0/.next/server/pages/blog/[slug].js:171:63)
    at buildStaticPaths (/vercel/path0/node_modules/next/dist/build/utils.js:487:37)
    at /vercel/path0/node_modules/next/dist/build/utils.js:622:121 {
  type: 'TypeError'
}
Error: Command "npm run build" exited with 1
Enter fullscreen mode Exit fullscreen mode

And my getStaticPaths function looks like you described it:

export async function getStaticPaths() {
  const allPosts = await getAllPostsWithSlug();

  return {
    paths: allPosts.edges.map(({ node }) => `/blog/${node.slug}`) || [],
    fallback: true
  };
}
Enter fullscreen mode Exit fullscreen mode

What might be wrong with deployment if it works fine locally and I can build it locally?

Collapse
 
a007mr profile image
a007mr • Edited

Ohh, I forgot to add global env for WP blog hehe. It works now. Thank you so much for article. It's brilliant!

Collapse
 
bsharptechnology profile image
bsharptechnology

This is a great article. Thanks for sharing. I originally used Next.js for my website it was so fast and snappy. But then I got sick of managing the content manually, so I move to WordPress. I love WordPress for its ability to build pages and content easily, but I have missed the Next.js install for its performance. Now I'm looking to combine the two to get the best of both worlds. Your guide has been great in helping achieve this.

A little problem though. I note the output for the post/page content includes shortcodes. Is there a way to deal with these and turn them into plain HTML for use in Next.js? I use the DIVI theme on my site now and it builds great looking pages, so it would be helpful to convert these to HTML and reuse them.

Collapse
 
robmarshall profile image
Robert Marshall

I came across this issue with shortcodes myself. I am not sure if this is exactly what you means, but it allows me to turn shortcode style snippets into NextJS React Components: robertmarshall.dev/blog/using-word...

Collapse
 
crisomg profile image
Cristian

Hola Ron, Excelente articulo! Todo me funcionó a la primera :D.

estuve investigando un poco y tengo una duda ¿Por que usar la propiedad "dangerouslySetInnerHTML"? ¿Es recomendable en este caso? ¿eso no dejaría una vulnerabilidad del tipo "xss"? en tal caso ¿Que nos recomendarías?

Collapse
 
varodesign profile image
VaroDesign

if your URL yourlink.com/graphql/ is getting a 404 error and you can't run your content on the blog page. Try to change your WordPress Settings > Permalinks to "Post name"

Collapse
 
pudpark profile image
Paul Barron

Has anyone run into this error?
Error: Failed to fetch API
I get a status 200 but nothing is returned.

Collapse
 
pudpark profile image
Paul Barron

Never mind. I t turns out that I was querying for the extraPostInfo but I never made in ACF. 😳😅

Collapse
 
tomhermans profile image
tom hermans

Wow. Great article. Done a similar thing with Nuxt and Gatsby, so a lot of familiar principles here. Since I'm exploring Nextjs now, will give this a go.

Collapse
 
kendalmintcode profile image
Rob Kendal {{☕}}

Thanks Tom, best of luck with your project :D

Collapse
 
ilirbajrami_ profile image
Ilir Bajrami

how can we add pagination to the blog page and "Next" "Previous" buttons to single posts?

Collapse
 
ds_sombol profile image
chabsombol

Do you have soft code?