Next.js Preview using @prismicio/client@^6.0.0

I've done my best following this guide: https://prismic.io/docs/technologies/previews-nextjs

while also following this migration: @prismicio/client v6 Migration Guide - Prismic

Right now it seems everything works. I hit preview, it opens my localhost, it goes to the page, it shows the loader, then it seems to refresh and error.

I tried to fit everything in this gist: [slug].tsx · GitHub

Any helpers would be huge thanks

Hi @beamer,

The preview documentation in the Next.js docs is not currently compatible with version v6 of @prismic/client, we're are currently working on releasing a much easier to use Next.js preview implementation in the following few weeks. Once this is released we'll update you here.

For the moment if you want to use previews with Next.js is best to stay on client v5.

Thanks.

1 Like

Hello @beamer @Phil I have same issue,
managed to hack working solution. You can use it while prismic update with official docs

// file name preview.ts
import * as prismic from '@prismicio/client'
import { linkResolver } from 'prismic/LinkResolver'
import { serialize } from 'cookie'

const accessToken = 'your token'
const repoName = 'your reponame'

const Preview = async (req, res) => {
  const { token, documentId } = req.query
  const endpoint = prismic.getEndpoint(repoName)
  const client = prismic.createClient(endpoint, {
    accessToken
  })

  client.enableAutoPreviewsFromReq(req)

  const redirectUrl = await client.resolvePreviewURL({
    linkResolver,
    defaultURL: '/',
    documentID: documentId,
    previewToken: token
  })

  res.setHeader('Set-Cookie', serialize('Preview_url', req.url, { path: '/' }))
  res.setPreviewData({ ref: token })
  res.writeHead(302, { Location: `${redirectUrl}` })
  res.end()
}

export default Preview

I'm using

"next": "^12.0.1",
"@prismicio/client": "6.0.0",
1 Like

Hello @juskeviciusarn

Yes, that's the way you can get work Previews in your Next.js Project. Thanks.

@beamer, I have checked your project code. You are currently passing req in the Client function, but it needs to be set up differently.

You need to enable the client to automatically query content from a preview session if one is active in server environments. This is disabled by default on the server. This change was made to make it very clear how the req object will be used.

You need to set req in client.enableAutoPreviewsFromReq(req). It will enable automatic previews from a server Request object.

Let me know if that doesn't fix it and I'll look again.

Thanks,
Priyanka

@everyone thank you for your help!! I'll try to implement this today and post any notes

@juskeviciusarn @Priyanka ok getting close.

Do you have an example of your getStaticProps that works with this?

My current:

export async function getStaticProps(context: GetStaticPropsContext) {
  const previewRef = context.previewData ? context.previewData["ref"] : null
  const refOption = previewRef ? { ref: previewRef } : null

  console.log("context.previewData", context.previewData)

  const page = await Client().getByUID(
    "page",
    context.params.slug as string,
    refOption
  )

  console.log(page)

  return {
    props: { page: { ...page.data, id: page.id }, previewRef },
  }
}

Loggers all seem correct, then it calls exit-preview and errors:

error - TypeError: Cannot read properties of null (reading 'predicates')

I can't get it work either. I've tried implementing the solution stated above but I keep getting a 500 error on production.

Here is my preview api route :

export default async (req: NextApiRequest, res: NextApiResponse) => {
  const { token: ref, documentId } = req.query;

  PrismicClient().enableAutoPreviewsFromReq(req);

  if (typeof ref === 'string' && typeof documentId === 'string') {
    const redirectUrl = await PrismicClient(req).resolvePreviewURL({
      linkResolver,
      defaultURL: '/',
      documentID: documentId,
      previewToken: ref,
    });

    if (!redirectUrl) {
      return res.status(401).json({ message: 'Invalid token' });
    }

    // When removing ...
    res.setHeader(
      'Set-Cookie',
      serialize('Preview_url', req.url, { path: '/' })
    );
    res.setPreviewData({ ref });
    // this it works => no 500 but no data obviously

    res.writeHead(302, {
      Location: `${redirectUrl}`,
    });
    return res.end();
  }

  return res.status(404).json({ message: 'ref not found' });
};

And here is my getStaticProps if needed :

export const getStaticProps: GetStaticProps = async ({
  previewData,
  locale,
}: GetStaticPropsContext) => {
  // @ts-ignore
  const previewRef = previewData ? previewData.ref : null;
  const refOption = previewRef ? { ref: previewRef } : null;
  const lang = nextLocaleToPrismicLocale(locale);

  const doc: PrismicDocument | null = await homePageQuery(refOption, lang);
  const footer: PrismicDocument | null = await footerQuery(refOption, lang);

  const serviceCategoriesData = await getServiceCategories();
  const serviceCategories = serviceCategoriesData?.data?.categories || [];
  const docWithIdsAddedToSlices = addUniqueIdsToSlices(doc);

  console.log(process.env.NODE_ENV);
  console.log('previewRef', previewRef);

  return {
    props: {
      previewRef,
      footer,
      doc: docWithIdsAddedToSlices,
      locale,
      serviceCategories,
      // Will be passed to the page component as props
      ...(await serverSideTranslations(locale, [
        'common',
        'dataset',
        'SupplierSearchForm',
        'FaqQuestions',
      ])),
    },
  };
};

@beamer are you using slice machine?
My data fetching looks something like this. next-slicezone - npm

@romain I guess you are not using slicemachine.

I'm not familiar with prismic-client v6 that much. But if you data fetching part is working correctly? What I mean, is your serviceCategoriesData returns data with preview data?

Because at this point, you will pass data to components which will be rendered. So we have to get preview before return.

Yes my data fetching was working correctly. I managed to find the solution. The error came from my next-i18next config where I had to add this line

    localePath: path.resolve('./public/locales'),

I guess the problem was in my getStaticProps where I was awaiting serverSideTranslations but it couldn't find my locales.

Anyway thank you guys for the help! :slight_smile:

2 Likes

Hello @beamer,

That error happens because null is an invalid input for the options parameter. That line could be changed to this:

const refOption = previewRef ? { ref: previewRef } : undefined
or
const refOption = previewRef ? { ref: previewRef } : {}

But we would actually recommend using the queryContentFromRef() method instead.

You can see an example of a createClient() function and how it’s used. I am sharing zip files with you.

pages.zip (4.8 KB)
prismicConfiguration.js.zip (641 Bytes)

Used getStaticProps in a pages.
The createClient function in a prismicConfiguration.js file.
Used resolvePreviewURL in a "preview.js' file.

Let me know if you have any further questions related to it.

Thanks,
Priyanka

@Priyanka this is SO helpful. I don't know where I got the code previously - i thought i was doing best practices. I don't think i realized the new docs were still coming out.

ok so i'm close! i believe this is working. but do you mind sharing me your SliceZone component from components/post?

In this project I was using SliceZone from @prismicio/react

but in another project I've hacked together a working next-slicezone - but there was a slice capitalization issue. I made a workaround that maps the names to camel case but - requires some manual attention.

I feel like i'm just doing it wrong

Thanks!

should i be using this?

a-ha i see now

Upgrading from next-slicezone
from @prismicio/react replaces the component from the next-slicezone package.

I can probably figure it out from here but this was a great help

I am glad that it works for you. Let us know if you have any questions.

Hello I'm still experiencing some issues with the new prismic client (v6) and previews.

I've noticed that the getByID method does not work if you use a doc id for a document that is in another locale than the default one. For example, my repo default locale is in fr-fr so this works

  const TestFR = await PrismicClient().getByID('YaeTGBMAACwAvDyO');

But this does not work

const TestEN = await PrismicClient().getByID('YbcIJRUAAC0Anw66')

unless I specifically add the lang in params like this

 const TestEN = await PrismicClient().getByID('YbcIJRUAAC0Anw66', {
    lang: 'en-gb',
  });

So the problem is that the resolvePreviewURL is not returning any document when trying to preview a "en-gb" document because it does not find it, here is the part causing this :

if (documentID != null) {
	const document = await this.getByID(documentID, {
		ref: previewToken,
	});

So basically preview does work for fr-fr docs but as soon as I try to preview a doc from another locale preview breaks, here is the error

PrismicError: No documents were returned

+1 - I am having the exact same issue when previewing non master locales.
Master locale previews work fine (published and unpublished content), but I cannot preview data from any non master locale. I get the same error.

Hello @romain @sarah1

You need to pass lang params option even though you are querying the document with the ID. To solve your previews issue, I need more details:

  1. How did you configure the link resolver?
  2. How are you initializing the Client?

It would be better to share your project (either GitHub URL or Zip file) with us. You can share with me by Private message.

Thanks,
Priyanka

1 Like

Hello @romain

I have looked into your files. I could not find next.config.js into that.
In nextjs, there are different properties available for language redirection, such as locale, locales, and defaultLocale . These properties need to be used in next.config.js.

Please find more details

  1. In next.config.js from our example project
  2. Nextjs documentation on routing

Let me know if you have further questions.

Thanks,
Priyanka

Hello @romain @sarah1

It's a known issue with @prismicio/client version 6.0.0. If you have the older version, can you update @prismicio/client to v6.1.0? It includes a fix for previewing documents from locales other than the master locale.

Thanks,
Priyanka