Serving static documents has all sorts of benefits for sites and project workflows (see Why Jamstack?). But editing static sites isn’t fun without a visual editor, especially for content authors who have gotten accustomed to the WYSIWYG experience of traditional content management systems (CMSs). Running a full build of a static site only to see what a minor change looks like just isn’t good enough.
Developers have found an answer to this problem by improving their experience with static site generation (SSG) approaches, using, for example, Next.js’ Preview Mode. But what about the marketers?
A flexible visual editing experience that, for example, allows marketers to place components, control column layouts, and add content, gives them more control over the design of the experience.
In this blog post, I will look at how we can enable marketers to visually edit and preview static pages by connecting the Magnolia Digital Experience Platform (DXP) to a Next.js app built with Netlify.
Building Blocks
Let’s look at a tech stack that allows you to create and serve static sites while enabling authors to edit content visually.
Framework: Next.js
This application is built with Next.js, a leading React framework. The framework allows us to take full advantage of static site generation and offers preview mode. Preview mode can bypass SSG and server-side render a draft page via any data fetching solution. This means we won’t have to run a full build to see a preview of the page. This is ideal if you’re using a content management system (CMS) for your web apps and your team wants to check what their content might look like before committing a change.
Next.js Hosting and Deployment: Netlify
We’ll build and host the site with Netlify. Netlify enhances the power of Next.js by offering us additional developer experience benefits, as well as tools for release management. It also offers excellent Next.js support, including full support for Next.js Preview Mode, which will be important in this tutorial.
Digital Experience Management: Magnolia DXP
Magnolia serves as the content hub and digital experience platform (DXP). Its Visual SPA Editor connects the modern SPA architecture with the concept of a traditional page editor, allowing content authors to create experiences in a WYSIWYG fashion.
Magnolia can also integrate data and content from Digital Asset Management (DAM) systems, eCommerce platforms, or any other 3rd-party systems, offering non-technical users one central hub to manage digital experiences.
Next.js
My Next.js code for this app offers a 2-in-1 solution, and you can find it on GitHub.
Static Site Generation
Next.js can export your Next.js application as static HTML files that can be run without a Node.js server.
I used both getStaticProps
and getStaticPaths
to generate the static site. Here are the links to where they live in the repo, and what each function does:
getStaticProps
- fetch page content from the headless CMSgetStaticPaths
- return page sitemap, telling Next.js which pages to build
Preview Mode
To understand how Next.js Preview Mode works, I recommend you take a look at the following scripts:
/pages/api/preview.js
/pages/[[...pathname]].js
The first file creates an API route in our Next.js project that allows us to bypass static site generation:
export default function handler(req, res) {
res.setPreviewData({
query: req.query,
});
res.redirect(req.query.slug);
}
Calling setPreviewData
on the response object sets a preview cookie. Next.js will consider all requests containing this particular cookie as preview requests.
The argument we pass to setPreviewData
should be an object. We can use getStaticProps
to retrieve its content later.
If the preview cookie is set, the API redirects the request to the page defined by the query parameter slug
.
The workflow looks like this:
- Open
/api?slug=/my-page
- Set the cookie
- Redirect to
/my-page
The next step is updating getStaticProps
to support preview mode.
When the preview cookie is set, the supplied context object has these special properties:
context.preview
istrue
context.previewData
equals the argument previously passed tosetPreviewData
We can now modify the function to fetch the content of the page that we passed as previewData
. In this example, we define which page should be rendered: the dynamically generated page or the static page returned by the getStaticPaths
function.
export async function getStaticProps(context) {
const resolvedUrl = context.preview
? context.previewData.query.slug
: context.params.pathname
? '/' + context.params.pathname.join('/')
: '';
// ...
// Find out page path in Magnolia
let pagePath = context.preview
? nodeName + resolvedUrl.replace(new RegExp('.*' + nodeName), '')
: nodeName + resolvedUrl;
// ...
// Fetching page content
const pagesRes = await fetch(setURLSearchParams(pagesApi + pagePath, 'lang=' + currentLanguage));
// ...
}
Setting Up Netlify
We have to set up two Netlify sites:
- To generate site previews for content authors
- To generate and serve the static site to the end user
Next.js Preview Mode Instance on Netlify
For the Next.js Preview Mode instance, we follow the documentation of How to Deploy Next.js Sites to Netlify. The Next.js on Netlify Plugin performs the required steps for us. Since Netlify will auto-detect if you’re building a Next.js app, it can install the plugin for you automatically.
We then only have to point the new site to our Git repository and let Netlify handle the rest.
Static Site Generation and Hosting
We point this site to the same Git repository.
To export the page as static HTML files, the build runs npm run build && npm run export
and uses the publish directory out
.
Next, we need to set two environment variables:
NETLIFY_NEXT_PLUGIN_SKIP
- skip the Next on Netlify Plugin setup for static site hostingNEXT_PUBLIC_MGNL_HOST
- Magnolia public instance URL to fetch published content
Lastly, we create the build hook to trigger static site generation when an editor publishes new content in Magnolia.
Magnolia
We need two Magnolia instances:
- An author instance for content authors to manage their content
- A public instance to serve published content
To use the Next.js Preview Mode instance, we have to set two properties in Magnolia’s page template definition: baseUrl
and routeTemplate
.
title: 'Next.js SSG: Basic'
baseUrl: https://nextjs-magnolia-netlify-preview.netlify.app
routeTemplate: '/api/preview?slug=/{language}{{@path}}'
You can find these templates in GitHub.
Next, we set up Magnolia’s Netlify extension that enables content authors to trigger the generation of the static site in Netlify when they publish new content.
We have to add the Netlify API key to the YAML configuration file /decorations/netlify-integration/config/config.yaml
.
apiToken: your_netlify_api_token;
Voila! We are now able to edit pages in Magnolia’s WYSIWYG editor and trigger a new Netlify build when new content is published.
❤️ the Visual Authoring Experience for Headless
Despite the growing adoption of the headless approach, we must not forget about our colleagues, the content authors. It is high time to bring them back into the equation and make sure that their experience is just as smooth as the developer experience.
If you like this solution, feel free to check out the example in our repository.