Using Prismic with Nuxt.js

This article discusses how to use Prismic with Nuxt.js and how it's different than standard Vue.js.

Nuxt.js is a hugely popular solution within in the Vue.js community when it comes to dealing with SSR applications & Vue.js. This community project is built on top of the Vue ecosystem and handles all aspects of a production-ready server rendered app. Another great aspect of Nuxt.js is that you can use it as a static site generator. Here is a link to learn more about Nuxt.js.

There are a few things to consider, though, when developing with Nuxt.js and Prismic in comparison to using standard Vue.js.

If you would like to use a link resolver you should create your link-resolver.js file in the plugins directory of your project. Then reference it in the nuxt.config.js file like below. Now you can use the link resolver in your project.

Copy
plugins: [
  '~/plugins/link-resolver.js',
],


Using the HTML Serializer

If you want to use the HTML serializer then it's the same process as above. In the standard Vue.js HTML Serializer we the <router-link> tag when links are generated in the 'Rich Text' sections because the standard anchor tags <a> will refresh the page and this is unwanted behaviour. With Nuxt.js this is slightly different, we use the <nuxt-link> tag when generating links in the HTML Serlializer. You can read more about why Nuxt.js uses the <nuxt-link> component in their docs.

Take a look below at the full HTML Serlializer code that you should use with Nuxt.js and Prismic:

Copy
import linkResolver from "./link-resolver"
import prismicDOM from 'prismic-dom'

const Elements = prismicDOM.RichText.Elements

export default function (type, element, content, children) {
  // Generate links to Prismic Documents as <router-link> components
  // Present by default, it is recommended to keep this
  if (type === Elements.hyperlink) {
    let result = ''
    const url = prismicDOM.Link.url(element.data, linkResolver)

    if (element.data.link_type === 'Document') {
      result = `<nuxt-link to="${url}">${content}</nuxt-link>`
    } else {
      const target = element.data.target ? `target="'${element.data.target}'" rel="noopener"` : ''
      result = `<a href="${url}" ${target}>${content}</a>`
    }
    return result
  }

  // If the image is also a link to a Prismic Document, it will return a <router-link> component
  // Present by default, it is recommended to keep this
  if (type === Elements.image) {
    let result = `<img src="${element.url}" alt="${element.alt || ''}" copyright="${element.copyright || ''}">`

    if (element.linkTo) {
      const url = prismicDOM.Link.url(element.linkTo, linkResolver)

      if (element.linkTo.link_type === 'Document') {
        result = `<nuxt-link to="${url}">${result}</nuxt-link>`
      } else {
        const target = element.linkTo.target ? `target="${element.linkTo.target}" rel="noopener"` : ''
        result = `<a href="${url}" ${target}>${result}</a>`
      }
    }
    const wrapperClassList = [element.label || '', 'block-img']
    result = `<p class="${wrapperClassList.join(' ')}">${result}</p>`
    return result
  }

  // Return null to stick with the default behavior for everything else
  return null
}

Then just like last time, reference it in the nuxt.config.js file like below. Now you can use the HTML Serializer in your project.

Copy
plugins: [
  '~/plugins/link-resolver.js',
  '~/plugins/html-serializer.js',
],


Adding the prismic-vue plugin as dependency

This is the biggest difference when using Prismic with Nuxt.js. We have made changes to the standard prismic-vue plugin so that it works better with SSR. So to install this modified version as a dependency to your project. Launch the terminal (command prompt or similar on Windows), point it to your project location and run the following command:

Copy
npm install https://github.com/prismicio/prismic-vue.git#nuxt

The next thing you need to do is add a file called prismic-vue.js to the plugins folder in your Nuxt project. Inside this file add the following lines.

Copy
import Vue from 'vue'
import PrismicVue from 'prismic-vue'
import linkResolver from "./link-resolver"
import htmlSerializer from './html-serializer'

Vue.use(PrismicVue, {
  linkResolver,
  htmlSerializer
})

Then finally in your nuxt.config.js file you need to add the following line to the plugin is loaded before mounting the app.

Copy
plugins: [
  '~/plugins/link-resolver.js',
  '~/plugins/html-serializer.js',
  '~/plugins/prismic-vue.js',
],

Now if you have followed these steps correctly you will have access to use the primsic-vue kit in the template section of your pages and components. So now it's just the same with as templating when when using our standard Vue.js kit.


Defining your API endpoint and include the Prismic Toolbar script

Now we will add a global variable defining your Prismic repository API endpoint, and we will include the Prismic Toolbar script. This step is also important for creating previews. Note that you have to define your API endpoint as a global variable before including the Prismic Toolbar script.

Create a file called prismic.config.js in the root of your project and add the following code and update the endpoint with you repository name:

Copy
var api = {
  apiEndpoint: "https://your-repo-name.cdn.prismic.io/api/v2",
}

module.exports = api;

Then in your nuxt.config.js import the information using the following line.

Copy
const PrismicConfig = require('./prismic.config')

Finally in the head section of your nuxt.config.js file add the following script which will add this information to the head of all your pages.

Copy
head: {
    script: [
        { innerHTML: '{ window.prismic = { endpoint: "' + PrismicConfig.apiEndpoint + '"} }' },
        { src: '//static.cdn.prismic.io/prismic.min.js' }
    ],
    __dangerouslyDisableSanitizers: ['script'],
},


Using the prismic-javascript plugin to Query the API

To query the API in the different pages of your website when using Nuxt.js you will need to install the prismic-javascript plugin as a dependency to your project. To do this launch the terminal (command prompt or similar on Windows), point it to your project location and run the following command:

Copy
npm install prismic-javascript

Then to use this plugin in your Nuxt.js pages and components, you need to import the plugin to the file. To do that simply add this line inside the <script> section of your page or component. You will also need to import your API endpoint that we set up in the previous step so you can reference this in your query.

Copy
import Prismic from "prismic-javascript"
import PrismicConfig from "~/prismic.config.js"


Querying the API with Nuxt.js example

Now that you've installed the prismic-javascript plugin you can query the API like with standard Javascript. When creating a server side rendered app and querying the Prismic API with Nuxt.js, a good practice is to use the asyncData lifecycle function when requesting the data. When you do this you can pass the error method to show an error page by creating a try/catch block.

We also pass in the `req` so we can access cookies and create previews. We get the API endpoint from the file we created earlier and pass in the req.

In the following example, we query by single as we would with standard Vue.js. Then we set the response as document and return it to be used in the template. We also return the document ID as a variable `documentId`.

Copy
async asyncData({context, error, req}) {
  try{
    const api = await Prismic.getApi(PrismicConfig.apiEndpoint, {req})

    let document = {}
    const result = await api.getSingle('custom_type')
    document = result.data

    // Load the edit button
    if (process.client) window.prismic.setupEditButton()

    return {
      document,
      documentId: result.id,
    }
  } catch (e) {
    error({ statusCode: 404, message: 'Page not found' })
  }
}


Using the edit button

Finally to use the the edit button on the page, first you add the <prismic-edit-button> inside the <template> section of your Vue document as you would with standard Vue.js. Then attach the document ID.

Copy
<prismic-edit-button :documentId="documentId"/>

The final step is to add the following code in the <script> section of your pages. We add this code inside the try block of your asyncData function, before the return statement. What this code does is force the client side of our app to show the edit button.

Copy
// Load the edit button
if (process.client) window.prismic.setupEditButton()


Setting up your preview route

To use previews you will need to create a Vue page in the root of your pages folder. Inside this page you can create a simple template with something like the following:

Copy
<p>Loading the Prismic's Preview...</p>

Then in the script section you will need to import the prismic-javascript kit, the Link Resolver, and the prismic.config.js. Then inside the asyncData function you will get the preview token and the API endpoint, then use the Link Resolver to create the url to redirect the app to the relevant page with the data to be previewed. See the full code below:

Copy
import Prismic from "prismic-javascript"
import LinkResolver from "~/plugins/link-resolver.js"
import PrismicConfig from "~/prismic.config.js"

export default {
  name: 'Preview',
  async asyncData({ query, redirect }) {
    let previewToken = query.token
    const api = await Prismic.getApi(PrismicConfig.apiEndpoint)
    const url = await api.previewSession(previewToken, LinkResolver, '/')
    redirect(url)
  },
}


Deploying your application

We recommend deploying your Nuxt.js and Prismic application with Heroku, but there are lots of other options that the Nuxt website explains in detail and which you can read more about here.


A full working example project with Nuxt.js

Feel free to explore our fully working example blog project using Nuxt.js and Prismic.

Nuxt.js Blog Example Project