Skip to content

Next.js preview mode with headless Craft CMS

Date: /Author: Daniel Kudwien

Craft CMS supports a headless backend mode. Learn how to connect Next.js preview mode in your website's frontend.

Craft CMS offers an awesome preview UI for seeing post changes in realtime. The problem we had to solve was connecting drafts live preview to a SSG (Static Site Generation) frontend. Next.js offers a preview mode and instructions on how to implement. This is how we got it working:

As stated in the docs we need a preview API route. We went with the recommended naming pages/api/preview.js:

import client from '@lib/apollo-client';
import { gql } from '@apollo/client';
import urlResolver from '@lib/url-resolver';

  const { data } = await client().query({
    query: gql`
      {
        entry(uid: "${req.query.entryUid}") {
          slug,
          typeHandle
        }
      }
    `,
  });

  res.setPreviewData({
    previewToken: req.query.token ?? null,
  });

  res.redirect(urlResolver(data.entry.typeHandle, data.entry.slug));

Once this was set, we are already able to see the response headers of the preview request by setting the __prerender_bypass and __next_preview_data cookies on the client.

Using Apollo, we instantiate the preview request parameters conditionally in our getStaticProps():

import { ApolloClient, gql, InMemoryCache } from '@apollo/client';
import PageQuery from '@queries/page.graphql';

export async function getStaticProps(context) {
  const { data } = await new ApolloClient({
    uri: context?.preview
      ? `${process.env.GRAPHQL_ENDPOINT}?token=${context.previewData.previewToken}`
      : `${process.env.GRAPHQL_ENDPOINT}`,
    cache: new InMemoryCache(),
  }).query({
    query: PageQuery,
    variables: { uri: context.params.uri.join('/') },
  });
  return {
    props: {
      ...data.entry,
    },
  };
}