Using Netlify functions to invoke NextJS preview mode

Hello,

I am building a NextJS site with data from Contentful and hosting on Netlify. I am trying to allow content editors in Contentful to view a preview of an entry before they publish it. I have followed this guide from NextJS and their Contentful example. I have successfully set up the preview mode in my local environment.

I think that what I need to do to allow the same functionality on the Netlify hosted site is create the equivalent api route in NextJS (/api/preview) in a Netlify function. Then I need to set the same cookies that this api route (/api/preview) sets using the method

res.setPreviewData({})

In my Netlify function.

So my questions are:

  • Is the the correct way of going about this?
  • If so, could someone point me in the direction of how I should go about setting the setPreviewData({}) cookies if the Netlify function does not have the same syntax as Next. e.g. Next:

export default async function preview(req, res) {

And Netlify functions (no res object)

exports.handler = async function preview(event, context) {

Thank you

Hey there,
Sorry for the delay here! We’re doing a lot of work right now to make NextJS work seamlessly with Netlify. First of all, we recommend using next-on-netlify- I couldn’t tell if you were already doing that? If not, then instructions for installing are in this blog post (also very relevant to your interests!):

Want to have a look and let us know if it addresses your questions?

Hi Jen, thank you for this. It’s great to work with so far. I do have a question about how you can access specific content to preview. For example in my next app, i can go to events/event-one where the directory is : events/[id].js.

When I use the preview, e.g. /.netlify/functions/next_events_id/, it is continually defaulting the preview to one of my events from Contentful but I don’t know how to specify how to get a specific event. Is there some syntax I should follow? e.g.

/.netlify/functions/next_events_id?id=event-one
or
/.netlify/functions/next_events_id?id=event-two

Thanks

hey @KWP !

can you confirm for me you are using next-on-netlify like jen suggested?

if so, once you’re using NoN, it will automatically convert your next app’s api handlers into Netlify functions. the name of your example function aka next_events_id suggests you are in fact using NoN.

if that’s the case, all you need to do in /api/preview is setPreviewData({}) as you have.

to actually see different events/content in your app in preview mode, you need to fetch different content in getStaticProps or getServerSideProps. see: https://github.com/vercel/next.js/blob/canary/examples/cms-contentful/pages/posts/[slug].js

feel free to add me to your repo and i can try to open a simple PR testing it out or make better suggestions with the additional context. my github is @lindsaylevine.

1 Like

Hi there @lindsaylevine, sorry for the delay. Finally getting back to this. I had this working but getting an error when trying to set preview data. When working locally, I am able to access preview mode and have the cookies set correctly to view preview content from Contentful, but when hitting the same function in Netlify, I get the below error:

{
errorType: "Runtime.UnhandledPromiseRejection",
errorMessage: "TypeError: e[t] is not a function",
trace: [
"Runtime.UnhandledPromiseRejection: TypeError: e[t] is not a function",
" at process.<anonymous> (/var/runtime/index.js:35:15)",
" at process.emit (events.js:314:20)",
" at processPromiseRejections (internal/process/promises.js:209:33)",
" at processTicksAndRejections (internal/process/task_queues.js:98:32)"
]
}

This is occurring on the res.setPreviewData({}) function from the below:

export default function handler(req, res) {
    res.setPreviewData({})
    res.end('Preview mode enabled')
}

My toml looks like this:

[build]
  command = "npm run build"
  functions = "out_functions"
  publish   = "out_publish"

[[plugins]]
  package = "@netlify/plugin-nextjs"

Package.json (scripts) looks like this:

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "export": "next export",
    "postbuild": "next-on-netlify"
  },

And then Next config looks like the below:

module.exports = withOptimizedImages({
  images: {
    domains: [
      'images.ctfassets.net'
    ]
  },
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      issuer: {
        test: /\.(js|ts)x?$/,
      },
      use: ['@svgr/webpack'],
    });
    return config;
  },
  target: "serverless",
});

I don’t know why the Netlify function is having difficulty setting the cookie. Any assistance would be appreciated. Thank you.

@KWP hey! check out this issue https://github.com/netlify/next-on-netlify/issues/99. currently, for preview mode to work in Next 10, you need your target to be experimental-serverless-trace. note that this will increase your build times and bundle sizes. we are working on that and possibly exploring how we’ll make preview mode work in Next 10 with target serverless. cheers!

1 Like