Bringing Dynamic WYSIWYG Editing to Static Next.js Sites
Jul 19, 2022
--

Bringing Dynamic WYSIWYG Editing to Static Next.js Sites

We’re excited about having been chosen as guest authors for an article on Netlify’s blog. Knowing how much developers love the Jamstack, we wanted to show the Netlify community how they can enable their non-technical users like marketers and content authors to edit their web apps in a visual editor while building and hosting the site with Netlify. Here’s a copy of the blog post:

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 offers a 2-in-1 solution and you can find it on Git.

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 the following functions to generate the static site:

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:

Bash
  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:

  1. Open /api?slug=/my-page

  2. Set the cookie

  3. 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 is true

  • context.previewData equals the argument previously passed to setPreviewData

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.

Bash
  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));
 
 // ...
}

Magnolia and Netlify

Create and deploy engaging websites and apps for maximum performance and the best user experience with Netlify.

Setting Up Netlify

We have to set up two Netlify sites:

  1. To generate site previews for content authors

  2. To generate and serve the static site to the end user

Preview Mode Instance

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 hosting

  • NEXT_PUBLIC_MGNL_HOST - Magnolia public instance URL to fetch published content

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.

Bash
  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 Git.

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.

Bash
  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.

If you want to see Magnolia and Netlify in action, watch our on-demand webinar about “Sharing the Fun of Headless with Your Marketers”.

About the author

Bartosz Staryga

Front-End Solution Architect, Magnolia

Bartosz is an expert in headless content management and front-end development at Magnolia. He designs and develops new Magnolia features and supports customers with their headless implementations from content types to APIs to integrations. Bartosz enjoys building new things and seeing them in action. He is also a trainer for Magnolia’s Headless training.