gatsby-plugin-prismic-previews
Integrate live Prismic Previews into a static
Gatsby site to enable editors a seamless content editing experience.
- Integrates tightly with the Gatsby Prismic source plugin
- Refreshes preview content automatically as changes are saved in Prismic
- Adds the Prismic Toolbar with an in-app edit button and
preview link sharing.
- No extra infrastructure or costs required (specifically, Gatsby
Cloud is not required)
Status
Install
npm install --save gatsby-plugin-prismic-previews@beta gatsby-source-prismic@beta gatsby-plugin-image
Or if you use Yarn:
yarn add gatsby-plugin-prismic-previews@beta gatsby-source-prismic@beta gatsby-plugin-image
Note that gatsby-source-prismic
and
gatsby-plugin-image
are a peer dependencies of this
plugin. The functionality of this plugin is closely connected to the source
plugin.
Migrating from gatsby-source-prismic
's previews
This plugin replaces the preview functionality provided by
gatsby-source-prismic
. If your site is set up for previews using the
source plugin, read the migration guide linked below to learn about the changes
needed to migrate.
Guide: Migrating from gatsby-source-prismic
How to use
First, you need a way to pass environment variables to the build process so
secrets and other secured data aren't committed to source control. We recommend
using dotenv
which will then expose environment variables. Read
more about dotenv and using environment variables here. Then
we can use these environment variables and configure our plugin.
module.exports = {
plugins: [
{
resolve: 'gatsby-source-prismic',
options: {
},
},
{
resolve: 'gatsby-plugin-prismic-previews',
options: {
repositoryName: process.env.GATSBY_PRISMIC_REPOSITORY_NAME,
accessToken: process.env.PRISMIC_ACCESS_TOKEN,
toolbar: 'new',
},
},
],
}
Some options must be provided to the plugin exactly as they are provided to
gatsby-source-prismic
. For example, if gatsby-source-prismic
is configured with a lang
option, that option must also be provided to
gatsby-plugin-prismic-previews
.
The following options should be provided to both gatsby-source-prismic
and gatsby-plugin-prismic-previews
with the same values:
repositoryName
apiEndpoint
graphQuery
fetchLinks
lang
imageImgixParams
imagePlaceholderImgixParams
typePrefix
See the gatsby-source-prismic
documentation for details on each option.
Connecting your pages
Once the plugin is configured in gatsby-config.js
, your app will need to be
conneted to the plugin's system. The following files will need to be created or
edited:
Gatsby Browser and SSR files
During a preview session, all content from your Prismic repository will be
fetched and stored in a shared React context. This context also contains
settings used by the preview system, like your plugin options.
Your app also needs to import a CSS file for the preview system's interface.
Users of your app will only see an interface during a preview session.
The following code must be added to your app's gatsby-browser.js
and
gatsby-ssr.js
files.
import * as React from 'react'
import { PrismicPreviewProvider } from 'gatsby-plugin-prismic-previews'
import 'gatsby-plugin-prismic-previews/dist/styles.css'
export const wrapRootElement = ({ element }) => (
<PrismicPreviewProvider>{element}</PrismicPreviewProvider>
)
The same contents should be added to gatsby-ssr.js
.
import * as React from 'react'
import { PrismicPreviewProvider } from 'gatsby-plugin-prismic-previews'
import 'gatsby-plugin-prismic-previews/dist/styles.css'
export const wrapRootElement = ({ element }) => (
<PrismicPreviewProvider>{element}</PrismicPreviewProvider>
)
Link Resolver function
When working with field types such as a
Link or a
Rich Text in a
Gatsby project, a function is required to convert a Prismic document to a
specific URL within your app.
This plugin will use your Link Resolver to send editors to the correct page in
your app during a preview.
See Prismic's documentation on creating a Link Resolver
for your app.
A simple example of a Link Resolver looks like this, but will need to be
customized for your app.
export const linkResolver = (doc) => {
switch (doc.type) {
case 'page':
return `/${doc.uid}`
case 'blog_post':
return `/blog/${doc.uid}`
default:
return '/'
}
}
Preview resolver page
The preview resolver page routes editors from the Prismic writing room to a
previewed document within your app. For example, if an editor clicks the preview
button for a blog post in the writing room, they will land on the preview
resolver page within your app, which then redirects them to the blog post with
previewed content.
Every app must have a preview resolver page to preview content. This page
usually will be created as /preview
by creating a page at
/src/pages/preview.js
. This page should be configured as the preview resolver
page in your Prismic repository's settings.
For more information on updating this setting within Prismic, see Prismic's
documentation on setting up previews.
This is what a simple preview resolver page could look like:
import * as React from 'react'
import { withPrismicPreviewResolver } from 'gatsby-plugin-prismic-previews'
import { linkResolver } from '../linkResolver'
const PreviewPage = () => {
return (
<div>
<h1>Loading preview…</h1>
</div>
)
}
export default withPrismicPreviewResolver(PreviewPage, [
{
repositoryName: process.env.GATSBY_PRISMIC_REPOSITORY_NAME,
linkResolver,
},
])
You can see that the Link Resolver provided to withPrismicPreviewResolver()
is
nested under your Prismic repository's name. This allows you to setup additional
repositories separately, if needed. For example, if your app displays content
from two repositories, each with their own Link Resolver, your
withPrismicPreviewResolver()
would look something like this:
import { mainLinkResolver } from '../mainLinkResolver'
import { secondaryLinkResolver } from '../secondaryLinkResolver'
export default withPrismicPreviewResolver(PreviewPage, [
{
repositoryName: process.env.GATSBY_PRISMIC_MAIN_REPOSITORY_NAME,
linkResolver: mainLinkResolver,
},
{
repositoryName: process.env.GATSBY_PRISMIC_SECONDARY_REPOSITORY_NAME,
linkResolver: secondaryLinkResolver,
},
])
For more details on setting up a preview resolver page and the available
customizations, see the
withPrismicPreviewResolver()
reference.
Content pages and templates
Your app's pages and templates usually contain GraphQL queries to Gatsby's data
layer to fetch content from Prismic. In order for this content to be updated
during a preview, pages must be connected to the preview system using a function
called withPrismicPreview()
. It
automatically updates a page's data
prop with content from an active preview
session as needed.
In order for this HOC to add preview content to your existing page data, you
must mark documents in your query as "previewable." This involves adding a
_previewable
field to your query.
This is what a simple preview-connected page template could look like:
import * as React from 'react'
import { graphql } from 'gatsby'
import { withPrismicPreview } from 'gatsby-plugin-prismic-previews'
import { linkResolver } from '../linkResolver'
const PageTemplate = ({ data }) => {
const page = data.prismicPage
return (
<div>
<h1>{page.data.title.text}</h1>
</div>
)
}
export default withPrismicPreview(PageTemplate, [
{
repositoryName: process.env.GATSBY_PRISMIC_REPOSITORY_NAME,
linkResolver,
},
])
export const query = graphql`
query PageTemplate($id: ID!) {
prismicPage(id: { eq: $id }) {
_previewable
data {
title {
text
}
}
}
}
`
The page template component is written as a standard Gatsby page without any
special preview-specific code. In most cases, you can simply add
withPrismicPreview()
around the default export to an existing page template to
enable preview support.
The page's query includes a _previewable
field for the queried document. This
tells the HOC to replace the document's data with preview content if available.
This special field should be included any time a document is queried, including
querying for documents within relationship fields.
You can see that the Link Resolver provided to withPrismicPreview()
is nested
under your Prismic repository's name. This allows you to setup additional
repositories separately, if needed. For example, if your app displays content
from two repositories, each with their own Link Resolver, your
withPrismicPreview()
would look something like this:
import { mainLinkResolver } from '../mainLinkResolver'
import { secondaryLinkResolver } from '../secondaryLinkResolver'
export default withPrismicPreview(PageTemplate, [
{
repositoryName: process.env.GATSBY_PRISMIC_MAIN_REPOSITORY_NAME,
linkResolver: mainLinkResolver,
},
{
repositoryName: process.env.GATSBY_PRISMIC_SECONDARY_REPOSITORY_NAME,
linkResolver: secondaryLinkResolver,
},
])
For more details on connecting your pages and templates to preview data and the
available customizations, see the
withPrismicPreview()
reference.
404 Not Found page
Your app's 404 page is displayed any time a user accesses a page that does not
exist. This can be used to our advantage when trying to preview a page that has
yet to be published. Because the page is not yet published, a page for it does
not exist in your app. As a result, we can override the normal 404 page and
render the previewed document instead automatically as needed.
This is what a simple unpublished preview 404 page could look like:
import * as React from 'react'
import { graphql } from 'gatsby'
import {
withPrismicUnpublishedPreview,
componentResolverFromMap,
} from 'gatsby-plugin-prismic-previews'
import { linkResolver } from '../linkResolver'
import PageTemplate from './PageTemplate'
const NotFoundPage = ({ data }) => {
const page = data.prismicPage
return (
<div>
<h1>{page.data.title.text}</h1>
</div>
)
}
export default withPrismicUnpublishedPreview(PageTemplate, [
{
repositoryName: 'my-repository-name',
linkResolver,
componentResolver: componentResolverFromMap({
page: PageTemplate,
}),
},
])
export const query = graphql`
query NotFoundPage {
prismicPage(id: { eq: "404" }) {
_previewable
data {
title {
text
}
}
}
}
`
For more details on supporting unpublished document previews and the available
customizations, see the
withPrismicUnpublishedPreview()
reference.
Prismic Toolbar
The Prismic Toolbar adds an in-app edit button when an editor
is signed into Prismic and automatic refreshing when content is updated in the
writing room. It also facilitates the preview process by setting up data in the
background that this plugin then reads.
By default, the newer, current version of the toolbar is used. All new and
recently created Prismic repositories will use this version of the toolbar and
requires no extra settings.
If your repository is older, it may not support the latest version of the
toolbar. Don't worry, previews will still work! But you will need to tell the
plugin to use an older version of the toolbar. To check if your repository
requires the older toolbar, perform the following steps:
-
Sign in to the writing room for your Prismic repository.
-
Navigate to your repository's Settings page.
-
Select the Previews section.
-
On that page, check the "Include the Prismic Toolbar JavaScript file" code
snippet.
If it looks like this, you can use the latest version of the toolbar which
requires no extra settings:
<script
async
defer
src="https://static.cdn.prismic.io/prismic.js?new=true&repo=your-repository-name"
></script>
If it looks like this, you need to use the "legacy" version of the toolbar
which requires setting the toolbar
plugin option:
<script>
window.prismic = {
endpoint: 'https://your-repository-name.cdn.prismic.io/api/v2',
}
</script>
<script
type="text/javascript"
src="https://static.cdn.prismic.io/prismic.min.js"
></script>
If you need to use the legacy version of the toolbar, update your plugin options
in gatsby-config.js
to include the following toolbar
option. This will
perform the toolbar setup described in the code snippet automatically.
module.exports = {
plugins: [
{
resolve: 'gatsby-plugin-prismic-previews',
options: {
toolbar: 'legacy',
},
},
],
}
Limitations
There are limitations to client-side previewing since it is only being processed
in your browser. Features that require build-time processing, such as
gatsby-transformer-sharp
or field aliasing, cannot
be handled within the browser.
See the Limitations documentation for a list of things
to keep in mind and useful strategies.