Skip to content

Commit 8024b3b

Browse files
committed
add rest api tutorial, update wpgraphql tutorial and index
1 parent 3c09485 commit 8024b3b

File tree

6 files changed

+307
-7
lines changed

6 files changed

+307
-7
lines changed

docs/plugins/hwp-previews/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ HWP Previews automatically integrates with [Faust.js](https://faustjs.org/) when
139139
* [Configure Previews](how-to/configure-previews/index.md)
140140
* [Integrate with Faust.js](how-to/integrate-with-faust/index.md)
141141

142+
### Tutorials
143+
* [Build Previews with Next.js and WPGraphQL](tutorial/previews-with-wpgraphql/index.md)
144+
* [Build Previews with Next.js and REST API](tutorial/previews-with-rest/index.md)
145+
142146
### Explanation
143147

144148
* [Core Concepts](explanation/core-concepts/index.md)
Lines changed: 297 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,300 @@
11
---
2-
title: "Implement Previews with REST API"
3-
description: "Learn how to implement preview functionality using the HWP Previews plugin in your headless WordPress application with REST API."
2+
title: "Build Previews with Next.js and REST API"
3+
description: "Learn how to build a Next.js application with WordPress preview functionality using the REST API and Application Passwords."
44
---
55

6-
@TODO
6+
## Overview
7+
8+
In this tutorial, we will build a Next.js application that displays WordPress content and enables preview functionality for draft posts. By the end, you will have a working headless WordPress setup where clicking "Preview" in WordPress opens your draft content in Next.js.
9+
10+
We will use Next.js Pages Router, WordPress REST API for data fetching, and WordPress Application Passwords for authentication.
11+
12+
> [!NOTE]
13+
> This tutorial uses the REST API. If you prefer WPGraphQL, see [Build Previews with Next.js and WPGraphQL](../previews-with-wpgraphql/index.md).
14+
15+
## What you'll build
16+
17+
By following this tutorial, you will create:
18+
19+
* A Next.js application that fetches WordPress content via REST API
20+
* An API route that enables Next.js Draft Mode for previews
21+
* Preview functionality that shows draft content when you click "Preview" in WordPress
22+
* Authentication using WordPress Application Passwords
23+
24+
## Prerequisites
25+
26+
Before starting, make sure you have:
27+
28+
* Node.js 18 or higher installed
29+
* A WordPress site with HWP Previews plugin installed
30+
* Basic familiarity with Next.js and React
31+
32+
## Step 1: Create the Next.js application
33+
34+
First, we will create a new Next.js project.
35+
36+
Open your terminal and run:
37+
38+
```bash
39+
npx create-next-app@latest my-wordpress-preview-rest
40+
```
41+
42+
When prompted, select:
43+
* TypeScript: No
44+
* ESLint: Yes
45+
* Tailwind CSS: Yes (optional)
46+
* App Router: No (we'll use Pages Router)
47+
48+
Navigate into your project:
49+
50+
```bash
51+
cd my-wordpress-preview-rest
52+
```
53+
54+
You should now see a basic Next.js project structure with a `pages` directory.
55+
56+
## Step 2: Create environment variables
57+
58+
Create a `.env.local` file in your project root:
59+
60+
```bash
61+
NEXT_PUBLIC_WORDPRESS_URL=http://your-wordpress-site.com
62+
63+
WP_USERNAME=admin # WordPress username which you created Application Password for
64+
WP_APP_PASSWORD=**** # WordPress Application Password
65+
WP_PREVIEW_SECRET=**** # Any strong secret string
66+
```
67+
68+
Use your actual WordPress URL and username here. We will cover the Application Password and the secret in a later step.
69+
70+
## Step 3: Create the authentication utility
71+
72+
We need a way to send WordPress credentials with our preview requests.
73+
74+
Create `src/utils/getAuthString.js`:
75+
76+
```javascript
77+
export function getAuthString() {
78+
const username = process.env.WP_USERNAME;
79+
const password = process.env.WP_APP_PASSWORD;
80+
81+
if (!username || !password) {
82+
return null;
83+
}
84+
85+
return "Basic " + Buffer.from(`${username}:${password}`).toString("base64");
86+
}
87+
```
88+
89+
This function creates a Base64-encoded authentication string from your WordPress credentials. You will use this when fetching preview content.
90+
91+
## Step 4: Create the fetch utility
92+
93+
We will create a helper function to fetch data from WordPress REST API.
94+
95+
Create `src/lib/fetchWP.js`:
96+
97+
```javascript
98+
export async function fetchWP(endpoint, authString = null) {
99+
const WP_URL = process.env.NEXT_PUBLIC_WORDPRESS_URL;
100+
const url = `${WP_URL}/wp-json/wp/v2/${endpoint}`;
101+
102+
const headers = {
103+
"Content-Type": "application/json",
104+
};
105+
106+
if (authString) {
107+
headers.Authorization = authString;
108+
}
109+
110+
const res = await fetch(url, { headers });
111+
112+
if (!res.ok) {
113+
return null;
114+
}
115+
116+
return res.json();
117+
}
118+
```
119+
120+
This function fetches from WordPress REST API and optionally includes an authorization header for draft content.
121+
122+
## Step 5: Create the preview API route
123+
124+
Now we will create the API route that enables Draft Mode when WordPress redirects to your preview.
125+
126+
Create `src/pages/api/preview.js`:
127+
128+
```javascript
129+
import { fetchWP } from "@/lib/fetchWP";
130+
import { getAuthString } from "@/utils/getAuthString";
131+
132+
export default async function handler(req, res) {
133+
const { secret, id } = req.query;
134+
135+
if (!id) {
136+
return res.status(400).json({ message: "No ID provided." });
137+
}
138+
139+
// Verify the secret token matches our environment variable for security
140+
if (secret !== process.env.WP_PREVIEW_SECRET) {
141+
return res.status(401).json({ message: "Invalid secret token." });
142+
}
143+
144+
// Query WordPress to verify the content exists and we can access it
145+
const post = await fetchWP(`posts/${id}`, getAuthString());
146+
147+
if (!post) {
148+
return res.status(404).json({ message: "Content not found." });
149+
}
150+
151+
// Enable Next.js Draft Mode for this session
152+
res.setDraftMode({ enable: true });
153+
// Redirect to the content page using the database ID
154+
res.redirect("/" + post.id);
155+
}
156+
```
157+
158+
This route does three important things:
159+
160+
1. Checks if the secret token matches (security)
161+
2. Verifies the content exists using REST API
162+
3. Enables Draft Mode and redirects to the content
163+
164+
## Step 6: Create the content display page
165+
166+
We will create a dynamic page that displays both published and preview content.
167+
168+
Create `src/pages/[identifier].js`:
169+
170+
```javascript
171+
import { fetchWP } from "@/lib/fetchWP";
172+
import { getAuthString } from "@/utils/getAuthString";
173+
174+
// This page handles both published content and preview content
175+
export default function Content({ post }) {
176+
if (!post) {
177+
return <div>Content not found</div>;
178+
}
179+
180+
return (
181+
<article>
182+
<h1 dangerouslySetInnerHTML={{ __html: post.title.rendered }} />
183+
<div dangerouslySetInnerHTML={{ __html: post.content.rendered }} />
184+
</article>
185+
);
186+
}
187+
188+
export async function getStaticProps({ params, draftMode }) {
189+
// Use different endpoints based on whether we're in draft mode
190+
// For previews, fetch by ID; for published posts, fetch by slug
191+
const endpoint = draftMode
192+
? `posts/${params.identifier}`
193+
: `posts?slug=${params.identifier}`;
194+
195+
// Only send auth header for preview requests
196+
const authString = draftMode ? getAuthString() : null;
197+
198+
const data = await fetchWP(endpoint, authString);
199+
200+
// Extract post from the appropriate format
201+
const post = draftMode ? data : data?.[0];
202+
203+
if (!post) {
204+
return {
205+
notFound: true,
206+
};
207+
}
208+
209+
return {
210+
props: { post },
211+
revalidate: 60,
212+
};
213+
}
214+
215+
export async function getStaticPaths() {
216+
return {
217+
paths: [],
218+
fallback: "blocking",
219+
};
220+
}
221+
```
222+
223+
Notice how this page handles both preview mode (using post ID) and normal mode (using slug). When Draft Mode is enabled, it sends authentication headers.
224+
225+
## Step 7: Generate a WordPress Application Password
226+
227+
Now we need to create an Application Password in WordPress for authentication.
228+
229+
1. Log into your WordPress admin
230+
2. Go to Users > Profile
231+
3. Scroll down to "Application Passwords"
232+
4. Enter a name like "Next.js Preview"
233+
5. Click "Add Application Password"
234+
235+
![WordPress Application Passwords section showing the form to generate a new application password with a name field and "Add Application Password" button](../screenshots/generate-application-password.png)
236+
237+
Copy the generated password (it will look like `xxxx xxxx xxxx xxxx xxxx xxxx`). You will not be able to see it again.
238+
239+
Update your `.env.local` file with this password:
240+
241+
```bash
242+
WP_APP_PASSWORD=xxxx xxxx xxxx xxxx xxxx xxxx
243+
```
244+
245+
## Step 8: Configure HWP Previews in WordPress
246+
247+
We will now configure the preview URL in WordPress to point to your Next.js app.
248+
249+
1. In WordPress admin, go to Settings > HWP Previews
250+
2. Click the "Posts" tab
251+
3. Check "Enable HWP Previews"
252+
4. In the Preview URL Template field, enter:
253+
```
254+
http://localhost:3000/api/preview?id={ID}&secret=YOUR_SECRET_TOKEN
255+
```
256+
5. Replace `YOUR_SECRET_TOKEN` with a random string (like `my-secret-preview-token-123`)
257+
6. Click "Save Changes"
258+
259+
![WordPress HWP Previews settings page showing the Posts tab with "Enable HWP Previews" checkbox checked and a Preview URL Template field containing the localhost preview URL](../screenshots/configure-hwp-previews.png)
260+
261+
Update your `.env.local` file with the same secret token:
262+
263+
```bash
264+
WP_PREVIEW_SECRET=my-secret-preview-token-123
265+
```
266+
267+
## Step 9: Start your application
268+
269+
Start the Next.js development server:
270+
271+
```bash
272+
npm run dev
273+
```
274+
275+
You should see output indicating the server is running at `http://localhost:3000`.
276+
277+
## Step 10: Test the preview
278+
279+
Now we will test that previews work correctly.
280+
281+
1. In WordPress, create or edit a post
282+
2. Make some changes but do not publish
283+
3. Click the "Preview" button
284+
285+
You should be redirected to your Next.js application showing your draft content. Notice the URL includes your post ID.
286+
287+
![Screenshot showing a Next.js application displaying WordPress draft content in preview mode, with the post title and content visible on the page](../screenshots/preview-view.png)
288+
289+
If you see your draft content, congratulations! Your preview system is working.
290+
291+
## Next steps
292+
293+
Now that you have a working preview system, you can:
294+
295+
* Add support for Pages and custom post types
296+
* Implement a "Disable Preview" button
297+
* Add loading states and error handling
298+
* Deploy your application to production
299+
300+
For an advanced implementation using App Router and JWT authentication, see the [complete example](https://github.com/wpengine/hwptoolkit/tree/main/plugins/hwp-previews/examples/hwp-preview-rest) which includes these additional features.

docs/plugins/hwp-previews/tutorial/previews-with-wpgraphql/index.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ In this tutorial, we will build a Next.js application that displays WordPress co
99

1010
We will use Next.js Draft Mode, WPGraphQL for data fetching, and WordPress Application Passwords for authentication.
1111

12+
> [!NOTE]
13+
> This tutorial uses WPGraphQL. If you prefer the REST API, see [Build Previews with Next.js and REST API](../previews-with-rest/index.md).
14+
1215
> [!TIP]
1316
> You can see the completed project in the [hwp-preview-wpgraphql example](https://github.com/wpengine/hwptoolkit/tree/main/plugins/hwp-previews/examples/hwp-preview-wpgraphql).
1417
@@ -21,7 +24,6 @@ By following this tutorial, you will create:
2124
* Preview functionality that shows draft content when you click "Preview" in WordPress
2225
* Authentication using WordPress Application Passwords
2326

24-
2527
## Prerequisites
2628

2729
Before starting, make sure you have:
@@ -275,7 +277,7 @@ Now we need to create an Application Password in WordPress for authentication.
275277
4. Enter a name like "Next.js Preview"
276278
5. Click "Add Application Password"
277279
278-
![WordPress Application Passwords section showing the form to generate a new application password with a name field and "Add Application Password" button](generate-application-password.png)
280+
![WordPress Application Passwords section showing the form to generate a new application password with a name field and "Add Application Password" button](../screenshots/generate-application-password.png)
279281
280282
Copy the generated password (it will look like `xxxx xxxx xxxx xxxx xxxx xxxx`). You will not be able to see it again.
281283
@@ -299,7 +301,7 @@ We will now configure the preview URL in WordPress to point to your Next.js app.
299301
5. Replace `YOUR_SECRET_TOKEN` with a random string (like `my-secret-preview-token-123`)
300302
6. Click "Save Changes"
301303
302-
![WordPress HWP Previews settings page showing the Posts tab with "Enable HWP Previews" checkbox checked and a Preview URL Template field containing the localhost preview URL](configure-hwp-previews.png)
304+
![WordPress HWP Previews settings page showing the Posts tab with "Enable HWP Previews" checkbox checked and a Preview URL Template field containing the localhost preview URL](../screenshots/configure-hwp-previews.png)
303305
304306
Update your `.env.local` file with the same secret token:
305307
@@ -327,7 +329,7 @@ Now we will test that previews work correctly.
327329

328330
You should be redirected to your Next.js application showing your draft content. Notice the URL includes your post ID.
329331

330-
![Screenshot showing a Next.js application displaying WordPress draft content in preview mode, with the post title and content visible on the page](preview-view.png)
332+
![Screenshot showing a Next.js application displaying WordPress draft content in preview mode, with the post title and content visible on the page](../screenshots/preview-view.png)
331333

332334
If you see your draft content, congratulations! Your preview system is working.
333335

docs/plugins/hwp-previews/tutorial/previews-with-wpgraphql/configure-hwp-previews.png renamed to docs/plugins/hwp-previews/tutorial/screenshots/configure-hwp-previews.png

File renamed without changes.

docs/plugins/hwp-previews/tutorial/previews-with-wpgraphql/generate-application-password.png renamed to docs/plugins/hwp-previews/tutorial/screenshots/generate-application-password.png

File renamed without changes.

docs/plugins/hwp-previews/tutorial/previews-with-wpgraphql/preview-view.png renamed to docs/plugins/hwp-previews/tutorial/screenshots/preview-view.png

File renamed without changes.

0 commit comments

Comments
 (0)