Skip to content

Commit

Permalink
chore(examples): misc improvements to the draft preview example (#10876)
Browse files Browse the repository at this point in the history
There were a number of things wrong or could have been improved with the
[Draft Preview
Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview),
namely:

- The package.json was missing `"type": "modue"` which would throw ESM
related import errors on startup
- The preview secret was missing entirely, with pointless logic was
written to throw an error if it missing in the search params as opposed
to not matching the environment secret
- The `/next/exit-preview` route was duplicated twice
- The preview endpoint was unnecessarily querying the database for a
matching document as opposed to letting the underlying page itself 404
as needed, and it was also throwing an inaccurate error message

Some less critical changes were:
- The page query was missing the `depth` and `limit` parameters which is
best practice to optimize performance
- The logic to format search params in the preview URL was unnecessarily
complex
- Utilities like `generatePreviewPath` and `getGlobals` were
unnecessarily obfuscating simple functions
- The `/preview` and `/exit-preview` routes were unecessarily nested
within a `/next` page segment
- Payload types weren't aliased
  • Loading branch information
jacobsfletch authored Jan 30, 2025
1 parent 8f27f85 commit 2b9ee62
Show file tree
Hide file tree
Showing 22 changed files with 1,275 additions and 1,330 deletions.
32 changes: 15 additions & 17 deletions docs/admin/preview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -61,35 +61,33 @@ preview: (doc, { req }) => `${req.protocol}//${req.host}/${doc.slug}` // highlig

## Draft Preview

The Preview feature can be used to achieve "Draft Preview", where you enter into a "draft mode" after clicking the preview button. While in "draft mode", you can adjust your page's query to include the `draft: true` in its params. Payload will read this param on the request, and when present, send back a draft document as opposed to a published one based on the document's `_status` field.
The Preview feature can be used to achieve "Draft Preview". After clicking the preview button from the Admin Panel, you can enter into "draft mode" within your front-end application. This will allow you to adjust your page queries to include the `draft: true` param. When this param is present on the request, Payload will send back a draft document as opposed to a published one based on the document's `_status` field.

To enter draft mode, the URL provided to the `preview` function can point to a custom endpoint in your front-end application that sets a cookie or session variable to indicate that you are in "draft mode". This is framework specific, so the mechanisms here very from framework to framework although the underlying concept is the same.
To enter draft mode, the URL provided to the `preview` function can point to a custom endpoint in your front-end application that sets a cookie or session variable to indicate that draft mode is enabled. This is framework specific, so the mechanisms here very from framework to framework although the underlying concept is the same.

### Next.js

If you're using Next.js, you can do the following code to enter draft mode.
If you're using Next.js, you can do the following code to enter [Draft Mode](https://nextjs.org/docs/app/building-your-application/configuring/draft-mode).

#### Step 1: Create an API Route
#### Step 1: Format the Preview URL

First, format your `preview` function to point to a custom endpoint that you'll open on your front-end. This URL will include a few key query search params:
First, format your `admin.preview` function to point to a custom endpoint that you'll open on your front-end. This URL should include a few key query search params:

```ts
import type { CollectionConfig } from 'payload'

export const Pages: CollectionConfig = {
slug: 'pages',
admin: {
preview: ({ slug }, { req }) => {
const path = `/${slug}`

preview: ({ slug, collection }) => {
const encodedParams = new URLSearchParams({
slug,
collection,
path,
previewSecret: process.env.PREVIEW_SECRET
path: `/${slug}`,
previewSecret: process.env.PREVIEW_SECRET || ''
})

return `/next/preview?${encodedParams.toString()}` // highlight-line
return `/preview?${encodedParams.toString()}` // highlight-line
}
},
fields: [
Expand All @@ -105,18 +103,17 @@ export const Pages: CollectionConfig = {

Then, create an API route that verifies the preview secret, authenticates the user, and enters draft mode:

`/preview/route.ts`
`/app/preview/route.ts`

```ts
import type { CollectionSlug, PayloadRequest, getPayload } from 'payload'
import type { CollectionSlug, PayloadRequest } from 'payload'
import { getPayload } from 'payload'

import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

import configPromise from '@payload-config'

const payloadToken = 'payload-token'

export async function GET(
req: {
cookies: {
Expand Down Expand Up @@ -161,12 +158,13 @@ export async function GET(

const draft = await draftMode()

// You can add additional checks here to see if the user is allowed to preview this page
if (!user) {
draft.disable()
return new Response('You are not allowed to preview this page', { status: 403 })
}

// You can add additional checks here to see if the user is allowed to preview this page

draft.enable()

redirect(path)
Expand All @@ -177,7 +175,7 @@ export async function GET(

Finally, in your front-end application, you can detect draft mode and adjust your queries to include drafts:

`/pages/[slug].tsx`
`/app/[slug]/page.tsx`

```ts
export default async function Page({ params: paramsPromise }) {
Expand Down
3 changes: 3 additions & 0 deletions examples/draft-preview/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ PAYLOAD_SECRET=YOUR_SECRET_HERE

# Used to configure CORS, format links and more. No trailing slash
NEXT_PUBLIC_SERVER_URL=http://localhost:3000

# Used to validate the preview request
PREVIEW_SECRET=YOUR_SECRET_HERE
2 changes: 1 addition & 1 deletion examples/draft-preview/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Payload Draft Preview Example

The [Payload Draft Preview Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview/payload) demonstrates how to implement draft preview in [Payload](https://github.com/payloadcms/payload) using [Versions](https://payloadcms.com/docs/versions/overview) and [Drafts](https://payloadcms.com/docs/versions/drafts). Draft preview allows you to see content on your front-end before it is published.
The [Payload Draft Preview Example](https://github.com/payloadcms/payload/tree/main/examples/draft-preview/payload) demonstrates how to implement [Draft Preview](https://payloadcms.com/docs/admin/preview#draft-preview) in [Payload](https://github.com/payloadcms/payload) using [Versions](https://payloadcms.com/docs/versions/overview) and [Drafts](https://payloadcms.com/docs/versions/drafts). With Draft Preview, you can navigate to your front-end application and enter "draft mode", where your queries are modified to fetch draft content instead of published content. This is useful for seeing how your content will look before being published.

## Quick Start

Expand Down
2 changes: 1 addition & 1 deletion examples/draft-preview/next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
1 change: 1 addition & 0 deletions examples/draft-preview/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "1.0.0",
"description": "Payload preview example.",
"license": "MIT",
"type": "module",
"main": "dist/server.js",
"scripts": {
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
Expand Down
Loading

0 comments on commit 2b9ee62

Please sign in to comment.