![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig1_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig1_HTML.jpg)
The default preview functionality
It would be nice if we could preview what the actual menu page would look like with the data we have added. Netlify CMS allows us to do this with custom previews.
Customizing Netlify CMS
The gatsby-plugin-netlify-cms plugin gives us a hook for configuring the CMS application. To get started, we need to make a change to the plugin configuration. Currently, in gatsby-config.js, our plugin entry for this plugin is a simple string. We will need to change that to the object format with resolve and options properties.
Updating the plugin configuration
The updated Gatsby configuration file
Here, we are adding an option called modulePath. This tells the CMS where to find customizations that we will create in this chapter. These customizations will be registered in the file src/cms/cms.js.
Adding a custom menu preview
Create a new directory called src/cms. All the CMS customizations will go inside this directory, including the cms.js module we specified in the preceding plugin configuration.
Refactoring the menu page
Currently, the menu page gets its data via a static query inside the component. In order for the preview to work, the page’s data must be passed to it from an external source. That’s currently not possible with the existing design.
Let’s refactor the menu page to use a page query. The results of the page query are passed to the page with a data prop. Later, when we render the preview page, we can pass CMS data into that data prop.
Using a page query instead of a static query
All we’ve done here is taken the GraphQL query from the static query and moved it to a page query, then added the data prop to the page component. The current menu page should still work as it did before.
Creating the preview component
The menu preview component
This preview component renders our menu page, passing in the data from the CMS. The template receives an entry prop, which is a data structure containing all of the CMS data.
entry.getIn(['data']) gets us a collection of the entry data. Calling toJS() on this converts it to a plain JavaScript object. This gives us the raw CMS data. However, we can’t pass this directly to the menu page, because it is expecting a data structure resembling the structure of its GraphQL page query. Before we pass this data to the page, we have to wrap it in some other data so that it appears to be the result of the GraphQL query.
Finally, we return the menu page component, passing in the correctly formatted data.
Registering the CMS preview
Opening the local CMS instance
To test these changes without needing to push to GitHub, we can actually access the CMS application locally at http://localhost:8000/admin. When you visit this page, you will again be prompted to log in with Netlify Identity.
![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig2_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig2_HTML.jpg)
The Development Settings dialog
Enter the full URL of your live site, for example, https://<your-site-name>.netlify.app, then click the “Set site’s URL” button. You will then be prompted to log in again. Log in with the same credentials you use on the live site, and you should be taken to the CMS application.
![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig3_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig3_HTML.jpg)
The CMS error message
If you look at the error details, you’ll see it is related to a StaticQuery. The query it is referring to is the one in the Layout component that queries for the site’s header background.
The preview components don’t go through the same build process that the Gatsby site pages do. Recall that the static query is executed at build time. Here, the browser tries to execute it at runtime on the page. The browser doesn’t know anything about GraphQL queries, so we get the error.
To fix this, we’ll have to do a little refactoring. Unfortunately, this means that our custom preview will not show the site header, as it is dependent on a static query. But we can still preview the menu page content with its styling.
Refactoring the menu page again
To make the menu page work in the custom preview, we’ll need to extract the page content into its own component that receives the page query data. The menu page component will be little more than a page query followed by the new component we’ll create, inside the Layout component.
The new Menu component
This component contains all of the content of the menu page, encapsulated into a presentational component. We’ll use this component both from the menu page, where the query results will be passed in, and the preview, where the CMS data will be passed in.
The CSS module for the Menu component
The new menu page
This page component no longer has any styling, so you can delete the file src/pages/menu.module.css.
At this point, the menu page should look exactly the same as it did before our refactoring. Go to http://localhost:8000/menu and make sure before continuing.
Updating the preview component
The updated MenuPreview component
Previewing the menu data
![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig4_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig4_HTML.jpg)
The CMS interface showing the editing controls alongside the preview
This is a live preview. This means that as you are making changes, the preview is updated immediately. The preview functionality is important for the site’s maintainability. The CMS provides the ability for the coffee shop management to update the menu without writing code, but without the custom preview, they won’t be able to see what the updated menu will look like to users of the site.
![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig5_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig5_HTML.jpg)
The new error
You’ll see that another error is thrown as soon as you click the button.
![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig6_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig6_HTML.jpg)
The error stack trace
In the MenuCategory component, we call map on the category’s items array in order to render each individual menu item. This is the root cause of the problem. When you click the “New category” button, the preview immediately tries to render the updated data.
At the moment when the category is first created, it does not have an items array yet – it is undefined. We call map on an undefined value, which throws the error.
The updated MenuCategory component
With this change, the call to map will now only occur if category.items is defined. This will fix the issue. We can test this out by refreshing the CMS page. You may be prompted to restore from a local backup. You can click “Cancel” to bypass this.
Now that we’ve refreshed the page, click “Add category” again. A new editor widget appears for the new category, which is currently blank. You might have also noticed that a new blank space appeared to the right of the items in the preview.
![../images/502348_1_En_12_Chapter/502348_1_En_12_Fig7_HTML.jpg](https://imgdetail.ebookreading.net/20201209/5/9781484262979/9781484262979__using-gatsby-and__9781484262979__images__502348_1_En_12_Chapter__502348_1_En_12_Fig7_HTML.jpg)
The live preview while adding a new category
Summary
Created a module to customize the CMS
Created a live preview component for the menu page
Refactored the menu page so that it works with the live preview
Fixed a few errors along the way