Check out a free preview of the full Production-Grade Next.js course

The "Implementing Preview Content" Lesson is part of the full, Production-Grade Next.js course featured in this preview video. Here's what you'd learn in this lesson:

Scott demonstrates how to implement the preview content and clear preview features using setPreviewData to redirect the user from the public page to draft content. This feature can be used in tandem with a GUI to easily switch between preview and public views for testing purposes.


Transcript from the "Implementing Preview Content" Lesson

>> So the first thing we need to do is let's create our preview functionality. So we're gonna go into pages, we're gonna make a new folder called API. Remember, if you make an API folder inside index j s, it's gonna create API routes, very much the same way that it does page routes.

So we're going make one for API and then we're going make it one call preview. Like that. And what we're gonna do here is we're just going to exports some default function here. That's gonna take a request objects and a response objects, just like that. And then I'm just going to type check this with the next API response.

There we go. And then all I'm going to do is I'm going to say rows dot set preview data like this. It's a function I'm gonna call it. Let's pass it in the object. Now I'm gonna pass into the object right now. There is some stuff you can pass here like the options object which is like a max age, basically.

So by default the cookie has like, I forgot what the default TTL or the time to live on this cookie is but you can override to be whatever you want. And we'll talk about the nuances of that. But basically, how long do you want this cookie to exist before it expires?.

And you'll see why you want this cookie to expire. If it doesn't it's going to lead to a lot of panic that I found out and a lot of confusion. So you really want this cookie to go away. Otherwise, it's not going to be a good day for some people, trust me.

[LAUGH] That'll make more sense in a minute. So we'll do that. And then what we want to do is we want to redirect the user back to the page that they wanted to see the preview on. So in order to do that, we need to know what page you want to see the preview on.

So we're going to require that you pass up a parameter on the URL of the route that you're interested in seeing a preview on so we can redirect you there. So we're gonna say rest redirect to whatever the request that query, that let's call it route. So you've gotta a query string with a route parameter on it, set that equal to whatever route that you want to see the preview on.

And as long as you do a get request here, will make that happen. So yeah, make that arrow function. There we go. So that's it. That's literally all you got to do to make the previous work. So what I'm gonna do now is just make sure this works.

It's not gonna do anything yet because we still got to hook it up to actual function but let's just make sure it works. So I'll go here, so I should be able to do a get request to slash API slash preview. And then I could do a query string with a route, like that.

I'm gonna say REL equals the Index page. So I wanna see your preview of the Index page. So if I hit enter, it's just gonna go back to the next page. Obviously, we don't have preview setup here yet, but we're about to do but if I go look at I don't know, maybe some cookies, memory application, go to cookies.

I should see some, there we go. Next preview. So next preview, which looks like a JJ Beatty was set here. Alright, so boom, we're in the previous state now, we're good to go, all right. Now what I need to do is need to make my pages aware of the preview I needed to respect the preview.

This is a very, very easy modification, especially if you already have a CMS. To do that, I'm going to go into my home index page grab this context object here. Then all I'm gonna do, instead of returning back to public page by default, I'm gonna say, well, let's look at context dot preview.

This is going to be a Boolean. It's going to be true, the cookie is set, it's going to be false. So the cookies not set. It's that simple. If we're in preview, then actually I want to the home dot draft. You're not, I want to do the home dot published.

That's it. Right. So now if I go back, and if the cookies still set, you can actually yeah, you can see, look, my content just changed automatically. Because even though I didn't hit the URL to go to the preview again, this cookie is still set. So it automatically showed me my draft content and you can see right here.

This is not some content that I want the world to see yet. This is my draft content. I want my published content. So, and this is why I said it might cause panic that cookie was lasting for like two days. And so like initiated a preview, and they only looked at it for five minutes and then they went to lunch.

And then they came back and they opened it back up and they went to the website and it still showed this. They will be, they will freak out. They will think that their draft content is now published, because they didn't click on preview to see this. But because the cookie is set your site loaded that up, right, it would freak them out.

So you want to wait to be able to clear this. So this is where I said you might want to adjust the TTL the time to live, but even then, it's like a race condition. Like how long is too long? How short is too short? There's really no perfect number that you can put in there.

I mean you can probably put one second and that way it literally only lasts one second. So as soon as you leave this tab, it's gone. I think that might work. But if you ever wanna be able to share previews, which I think is a really big feature that some CMS has started to implement and maybe you could too.

So where I want to send a link to someone so they can preview this content and approve it or not, then that TTL is not gonna work, right? You want to think about that. So, instead, you just want to clear it explicitly. So next js allows us to do that as well pretty easily.

So the way we can do that as you make another API route here, I'm gonna call this clear preview that TS and it's pretty much just gonna do the same thing here. I'm going to copy that except of setting the preview data is going to [COUGH] Clear preview data.

Right, and it's not gonna redicrect you anywhere cuz we don't need to I mean if you wanted a better experience, sure, but I'm just gonna say end and I'm just gonna say preview mode disabled. That's all I'm gonna do, okay? So we're gonna do that and then now if I go to /api/clearpreview Like that, you can see boom preview mode is disabled.

So we're good. So now if I go back to my Index page. I should be looking at my published content. Right. Pretty legit. So again, let's walk through it one more time. So if i want to see your preview of this homepage, I can say, do a get request to slash API slash preview with the route parameter equals to here.

This will show me a preview. I'm looking at a preview now. Now I'm done with this preview. I think it's. Good to go. So I'm gonna do a request to API / clear preview. And that's gonna clear it. So now when I go back, we're back on to publish.

Any questions on that? Okay, this is where I said this feature is meant for CMS. You see how we had to go in the URL and do that every time? You don't want to do that, that's really gross. You really want like a GUI that just says click here to preview this thing, right?

So that's where CMS comes in, because a CMS is a place that holds your content. So if you're looking at place where your content is if someone's in your teams like editing a markdown field or whatever, they can say I want to preview this markdown field on this blog post and it takes them there.

So that's why I'm saying next year has built this feature for CMS is to implement so you could use them. But there's nothing stopping you from building your own GUI. For instance, I could literally come down here I could just return them preview as a prop here, right?

I can say okay, ctx.preview, so now that's a prop. So that will appear. I get access to the preview if preview is true here. I can like put a whole gooey in here now, right? I can, I can do all types of stuff in here now, right? And then when we get to authentication, you can even detect that.

Okay? Not only does the user have to be logged in, but their email has to be one of the emails that exist in our organization. Then show them the gooey for preview. Right? You could do that. You'll be able to do this you can kind of build your own thing.

If you're just, if you're not using a CMS that has previews or if you're not using a CMS in general, you could just build your own thing, which actually is not a lot of work. Very powerful stuff. Okay, so we'll do the same thing for the blog page here.

This one is very much the same as the one we just did. The difference is going to be here, right? So, so doing posts from CMS. We're gonna say get the context here. And then we're gonna say, well, it really just depends on whether or not this is publishing ourselves a CTA preview.

If it isn't preview, then I'll do draft. If not, then I'll do that. Alright, that's it. So pretty much the same thing and then where it gets a little different is here in the slug. So in the slug, it's like, okay, well, you don't actually get access to the context.

There's no context objects and get static paths. So we can't check to see this preview here. So what that means is, there is absolutely no way to dine or to generate previews. At build time, because we don't know if you're in preview mode or not. So anything that you want to preview is not gonna be generated here.

So if you ever want to see it, well, you basically got to use fallback because the fallback was false.And you try to use previews.
>> And because previews can't be generated here, then if you just create a blog post with a new slug that doesn't exist on this built version of the site yet.

Then there's no way you'll be able to, there's no way you'll ever be able to preview it because it'll fail here. And because fallback is false, that was just four Four. So you have to put fallback true. If you want to look at previews on dynamic pages or even fall back blocking either one of those.

That way, I always did a skip here because it doesn't exist, it wasn't there before. I need to go a little straight down here and then it's pretty much the same thing, right? So we're just gonna look at the previous. We're gonna say params, we got a preview here, like that.

And it's pretty much the same thing, I was gonna just actually just, wait, where's it at? Go ahead and copy that thing, there we go. My goodness, what is it doing? There we go. And let's get rid of that context like that. So yeah, that's pretty much it, except for the posts.

Not postFromCMS in this file. Should have kept them consistent. There you go. Yeah, that's pretty much it and now we were able to preview this. So let's go check it out. So if I go here, I go to blog. You can see I got all my production blocks here.

I'm just on my published blog. So if I want to see some preview blocks. Okay, no problem. I go to API slash preview. And then what a route parameter equal to slash blog because that's the, that's the route that I want to preview. So I'll do that. And now you can see it's got the draft summary here.

We'll come up with this summary later, we'll come up with a summary later. This is the draft one, right? So, okay, now, that cookie is still set. So, if I go to read here, it'll probably show me the draft. Right shows me the draft post for this too, right.

So now if I clear the cookie I go back here. So, I say slash API slash clear preview, like that. Then I go back to that route. It just there's no hot reloads, messed up. There it is. So now you can see it shows me the published value for that blog now.

So pretty powerful stuff. I don't think I'll say this other frameworks like next as actually charge for this feature. You have to pay to be able to do this. This is free. It's just code. Other platforms, you have to pay for this. And then you have to pay for CMS to integrate into that.

So you paying twice for the same feature. Next, yes, this gives it to you for free. So because it's a full stack framework, other competing frameworks are not full stack frameworks. They're only static so they, it's literally not possible for them to do this. So I think that's just mind blowing.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now