Skip to content

Commit e37f36b

Browse files
Merge pull request #2410 from strapi/user/side-editor-preview-beta
Preview: Side panel
2 parents f4b97d0 + 94e69be commit e37f36b

File tree

4 files changed

+113
-26
lines changed

4 files changed

+113
-26
lines changed

docusaurus/docs/dev-docs/preview.md

Lines changed: 100 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@ The present page describes how to set up the Preview feature in Strapi. Once set
1919

2020
```bash
2121
CLIENT_URL=https://your-frontend-app.com
22-
PREVIEW_SECRET=your-secret-key # optional, required with Next.js draft mode
22+
PREVIEW_SECRET=your-secret-key
2323
```
2424

25+
The `PREVIEW_SECRET` key is optional but required with Next.js draft mode.
26+
2527
* A front-end application for your Strapi project should be already created and set up.
2628
:::
2729

@@ -78,7 +80,7 @@ preview: {
7880
//
7981
```
8082

81-
An example of [URL generation logic](#2-add-url-generation-logic) in given in the following basic implementation guide.
83+
An example of [URL generation logic](#2-add-url-generation) in given in the following basic implementation guide.
8284

8385
#### Previewing draft entries
8486

@@ -101,13 +103,15 @@ async handler(uid, { documentId, locale, status }) {
101103
},
102104
```
103105

104-
A more detailed example using the draft mode of Next.js is given in the [basic implementation guide](#3-add-handler-logic).
106+
A more detailed example using the draft mode of Next.js is given in the [basic implementation guide](#3-add-handler).
105107

106108
## Basic implementation guide
107109

108-
Follow these steps to add Preview capabilities to your content types.
110+
Follow these steps to add Preview capabilities to your content types in Strapi and your front-end.
111+
112+
This guide uses a basic Next.js example, but the process applies to all frameworks with some variations. Strapi-related steps (prefixed with [Strapi]) remain mostly the same. Please refer to your front-end framework's documentation for specific implementation details.
109113

110-
### 1. Create the Preview configuration
114+
### 1. [Strapi] Create the Preview configuration {#1-create-config}
111115

112116
Create a new file `/config/admin.ts` (or update it if it exists) with the following basic structure:
113117

@@ -127,7 +131,7 @@ export default ({ env }) => ({
127131
});
128132
```
129133

130-
### 2. Add URL generation logic
134+
### 2. [Strapi] Add URL generation logic {#2-add-url-generation}
131135

132136
Add the URL generation logic with a `getPreviewPathname` function. The following example is taken from the [Launchpad](https://github.com/strapi/LaunchPad/tree/feat/preview) Strapi demo application:
133137

@@ -177,7 +181,7 @@ const getPreviewPathname = (uid, { locale, document }): string => {
177181
Some content types don't need to have a preview if it doesn't make sense, hence the default case returning `null`. A Global single type with some site metadata, for example, will not have a matching front-end page. In these cases, the handler function should return `null`, and the preview UI will not be shown in the admin panel. This is how you enable or disable preview per content type.
178182
:::
179183

180-
### 3. Add handler logic
184+
### 3. [Strapi] Add handler logic {#3-add-handler}
181185

182186
Create the complete configuration, expanding the basic configuration created in step 1. with the URL generation logic created in step 2., adding an appropriate handler logic:
183187

@@ -225,12 +229,12 @@ export default ({ env }) => {
225229
};
226230
```
227231

228-
### 4. Set up the front-end preview route
232+
### 4. [Front end] Set up the front-end preview route {#4-setup-frontend-route}
229233

230234
Setting up the front-end preview route is highly dependent on the framework used for your front-end application.
231235

232236
For instance, [Next.js draft mode](https://nextjs.org/docs/app/building-your-application/configuring/draft-mode) and
233-
[Nuxt preview mode](https://nuxt.com/docs/api/composables/use-preview-mode) provide additional documentation on how to implement the front-end part in their respective documentations.
237+
[Nuxt preview mode](https://nuxt.com/docs/api/composables/use-preview-mode) provide additional information on how to implement the front-end part in their respective documentations.
234238

235239
If using Next.js, a basic implementation could be like in the following example taken from the [Launchpad](https://github.com/strapi/LaunchPad/tree/feat/preview) Strapi demo application:
236240

@@ -264,15 +268,100 @@ export async function GET(request: Request) {
264268
}
265269
```
266270

267-
### 5. Allow the front-end to be embedded
271+
### 5. [Front end] Allow the front-end to be embedded {#5-allow-frontend-embed}
268272

269273
On the Strapi side, [the `allowedOrigins` configuration parameter](#allowed-origins) allows the admin panel to load the front-end window in an iframe. But allowing the embedding works both ways, so on the front-end side, you also need to allow the window to be embedded in Strapi's admin panel.
270274

271275
This requires the front-end application to have its own header directive, the CSP `frame-ancestors` directive. Setting this directive up depends on how your website is built. For instance, setting this up in Next.js requires a middleware configuration (see [Next.js docs](https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy)).
272276

277+
### 6. [Front end] Detect changes in Strapi and refresh the front-end {#6-refresh-frontend}
278+
279+
Strapi emits a `strapiUpdate` message to inform the front end that data has changed.
280+
281+
To track this, within your front-end application, add an event listener to listen to events posted through [the `postMessage()` API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) on the `window` object. The listener needs to filter through messages and react only to Strapi-initiated messages, then refresh the iframe content.
282+
283+
With Next.js, the recommended way to refresh the iframe content is with [the `router.refresh()` method](https://nextjs.org/docs/app/building-your-application/caching#routerrefresh).
284+
<!-- TODO: use ExternalLink compo. -->
285+
286+
<Tabs groupId="js-ts">
287+
<TabItem value="js" label="JavaScript" >
288+
289+
```tsx title="next/app/path/to/your/front/end/logic.jsx" {6-17}
290+
export default function MyClientComponent({...props}) {
291+
//
292+
const router = useRouter();
293+
294+
useEffect(() => {
295+
const handleMessage = async (message) => {
296+
if (
297+
// Filters events emitted through the postMessage() API
298+
message.origin === process.env.NEXT_PUBLIC_API_URL &&
299+
message.data.type === "strapiUpdate"
300+
) { // Recommended way to refresh with Next.js
301+
router.refresh();
302+
}
303+
};
304+
305+
// Add the event listener
306+
window.addEventListener("message", handleMessage);
307+
308+
// Cleanup the event listener on unmount
309+
return () => {
310+
window.removeEventListener("message", handleMessage);
311+
};
312+
}, [router]);
313+
314+
// ...
315+
}
316+
```
317+
318+
</TabItem>
319+
<TabItem value="ts" label="TypeScript" >
320+
321+
```tsx title="next/app/path/to/your/front/end/logic.tsx" {6-17}
322+
export default function MyClientComponent({
323+
//
324+
const router = useRouter();
325+
326+
useEffect(() => {
327+
const handleMessage = async (message: MessageEvent<any>) => {
328+
if (
329+
// Filters events emitted through the postMessage() API
330+
message.origin === process.env.NEXT_PUBLIC_API_URL &&
331+
message.data.type === "strapiUpdate"
332+
) { // Recommended way to refresh with Next.js
333+
router.refresh();
334+
}
335+
};
336+
337+
// Add the event listener
338+
window.addEventListener("message", handleMessage);
339+
340+
// Cleanup the event listener on unmount
341+
return () => {
342+
window.removeEventListener("message", handleMessage);
343+
};
344+
}, [router]);
345+
346+
//
347+
})
348+
```
349+
350+
</TabItem>
351+
352+
</Tabs>
353+
354+
<details>
355+
<summary>Caching in Next.js:</summary>
356+
357+
In Next.js, [cache persistence](https://nextjs.org/docs/app/building-your-application/caching) may require additional steps. You might need to invalidate the cache by making an API call from the client side to the server, where the revalidation logic will be handled. Please refer to Next.js documentation for details, for instance with the [revalidatePath() method](https://nextjs.org/docs/app/building-your-application/caching#revalidatepath).
358+
<br/>
359+
360+
</details>
361+
273362
### Next steps
274363

275-
Once the preview system is set up, you need to adapt your data fetching logic to handle draft content appropriately. This involves:
364+
Once the preview system is set up, you need to adapt your data fetching logic to handle draft content appropriately. This involves the following steps:
276365

277366
1. Create or adapt your data fetching utility to check if draft mode is enabled
278367
2. Update your API calls to include the draft status parameter when appropriate

docusaurus/docs/user-docs/content-manager/previewing-content.md

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,36 @@ tags:
1111

1212
With the Preview feature, you can preview your front end application directly from Strapi's admin panel. This is helpful to see how updates to your content in the Edit View of the Content Manager will affect the final result.
1313

14-
<!-- TODO: add a dark mode GIF -->
15-
<ThemedImage
16-
alt="Previewing content"
17-
sources={{
18-
light: '/img/assets/content-manager/previewing-content.gif',
19-
dark: '/img/assets/content-manager/previewing-content.gif',
20-
}}
21-
/>
22-
2314
:::prerequisites
2415
- The Strapi admin panel user should have read permissions for the content-type.
2516
- The Preview feature should be configured in the code of the `config/admin` file (see [Developer Docs](/dev-docs/preview)).
2617
- A front-end application should already be created and running so you can preview it.
18+
- Additionally, the side panel is only available if you installed strapi with the beta flag, with the following command: `npx create-strapi@beta`.
2719
:::
2820

29-
When the Preview feature is properly set up, an **Open preview** button is visible on the right in the Edit View of the Content Manager. Clicking it will display the preview of your content as it will appear in your front-end application, but directly within Strapi's the admin panel:
21+
Once the Preview feature is properly set up, an **Open preview** button is visible on the right in the Edit View of the Content Manager. Clicking it will display a side panel with the preview of your content as it will appear in your front-end application, but directly within Strapi's the admin panel.
3022

3123
<!-- TODO: add a dark mode screenshot -->
3224
<ThemedImage
3325
alt="Previewing content"
3426
sources={{
35-
light: '/img/assets/content-manager/previewing-content.png',
36-
dark: '/img/assets/content-manager/previewing-content.png',
27+
light: '/img/assets/content-manager/previewing-content2.gif',
28+
dark: '/img/assets/content-manager/previewing-content2.gif',
3729
}}
3830
/>
3931

40-
From the Preview screen, you can:
32+
Once the side panel for the Preview is open, you can:
4133

4234
- click the close button ![Close button](/img/assets/icons/close-icon.svg) in the upper left corner to go back to the Edit View of the Content Manager,
4335
- switch between previewing the draft and the published version (if [Draft & Publish](/user-docs/content-manager/saving-and-publishing-content) is enabled for the content-type),
36+
- expand the side panel by clicking on the <Icon name="arrow-line-left" classes="ph-bold" /> button to make the Preview full screen
37+
- use buttons at the top right of the editor to define the assignee and stage for the [Review Workflows feature](/user-docs/content-manager/reviewing-content) if enabled
4438
- and click the link icon ![Link icon](/img/assets/icons/v5/Link.svg) in the upper right corner to copy the preview link. Depending on the preview tab you are currently viewing, this will either copy the link to the preview of the draft or the published version.
4539

40+
:::info
41+
The side panel and its expand button are only available if you run the beta version of Strapi. In the stable version, the "Open Preview" button will open a full-screen preview.
42+
:::
43+
4644
:::note
4745
In the Edit view of the Content Manager, the Open preview button will be disabled if you have unsaved changes. Save your latest changes and you should be able to preview content again.
4846
:::

docusaurus/sidebars.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ const sidebars = {
295295
label: 'Preview',
296296
id: 'dev-docs/preview',
297297
customProps: {
298-
new: true
298+
updated: true
299299
}
300300
},
301301
{
@@ -669,7 +669,7 @@ const sidebars = {
669669
type: 'doc',
670670
id: 'user-docs/content-manager/previewing-content',
671671
customProps: {
672-
new: true
672+
updated: true
673673
}
674674
},
675675
'user-docs/content-manager/adding-content-to-releases',
916 KB
Loading

0 commit comments

Comments
 (0)