CMS for SPAs: Building Vue and Nuxt Apps with CrafterCMS 4.0.x

Introduction

Nuxt.js is a free and open-source JavaScript library based on Vue.js, Node.js, Webpack, and Babel.js. Inspired by the NextJS project, NuxtJS also provide developers with plenty of features to boost development productivity. Building upon VueJS, NuxtJS offers great development features such as server-side rendering, automatically generated routes, improved meta tags managing, and SEO improvement.


CrafterCMS provides a full-featured editing toolset for content authors combined with comprehensive headless CMS capabilities for developers, and this combination is quite unique. In this tutorial, you will learn how to create a content-rich, NuxtJS-based web application with in-context editing and other easy to use content authoring capabilities.


Let’s get started.

Prerequisites

In this tutorial, you will need:


  • A CrafterCMS Studio 4 stable version running in port 8080 on your local machine

  • NodeJS version 16 or later installed in your machine

CrafterCMS sites with NuxtJS integration

For testing purposes, we have created a CrafterCMS site with NuxtJS integration. You can easily create a new site with this blueprint and check out how CrafterCMS works with NuxtJS.


Here is a sample site with NuxtJS integration: https://github.com/phuongnq/craftercms-example-nuxtjs


Let’s take a look at how to create a new site from this repository.


Demo sites with NuxtJS


Log in to Studio, from Sites tab, click Create Site button and select Remote Git Repository.


Input following in Create Site popup:



Note: Site name can be any but inputting “Nuxt JS” makes it easier for the setup.



Click Review > Create Site.


When the site “Next JS”  is created. You should see the following screen:



There are instructions on Readme to follow:


  1. In the CrafterCMS site sandbox directory, you'll find a directory called app, which is the Nuxt.JS app. Visit that directory on your terminal and run `yarn`

  2. Create a copy of app/.env.example to produce app/.env. If you named your site next-js and CrafterCMS is running on localhost:8080, no further edits are necessary; otherwise, change the file accordingly.

  3. Run `yarn dev` to start the node server on localhost:3000

  4. Open Site Tools and select "Configuration"

  5. Search for "Proxy Config"

  6. Comment line 58 and uncomment line 59

  7. Close the pop-up and refresh the page. You'll now see the next.js application in this area.

In your .env file, you should have the following content:


NUXT_ENV_CRAFTERCMS_HOST_NAME=http://localhost:8080
NUXT_ENV_CRAFTERCMS_SITE_NAME=nuxt-js



Follow the steps and run your Nuxt application on port 3000:



Update proxy configuration:



Do as these instructions, you should be able to see the following screen while previewing your site in port 8080:

While the green pencil is active, click on components such as the text “Welcome to NuxtJS on CrafterCMS “, you should see a green box appears showing that the text is editable. Click on it and change the text to “Welcome to NuxtJS on CrafterCMS 4“.

This is the In-Context Editing (ICE) feature of CrafterCMS that enables you to edit the content of your components while in previewing mode. If you open the site in port 3000, ICE is not available because we are opening the site out of Crafter Studio previewing frame.

How CrafterCMS works with NuxtJS


Similar to how CrafterCMS works with React, CrafterCMS works as the headless CMS for NuxtJS web applications. 


CrafterCMS provides craftercms/craftercms-sdk-js and the Experience Builder with built-in libraries to work with content, including In-Context Editing features. This library is tested working well with NuxtJS. Refer to the SDK in the GitHub repository for more information about supported modules and their usages.


Next, let’s take a look at the source code of our site.

This is a standard NuxtJS application, check out their official documentation to learn more.


  • pages: contains your application's views and routes.

  • components: your Vue.js components which are then imported into your pages.

  • layouts: Your application layout. By default, layouts/default.vue is used. Learn more about the layouts here.

  • lib/api.js: Include the CrafterCMS SDK JS to read content from Studio.

  • plugins: Additional plugins for NuxtJS application. In this case, we added `ice.js` as a small mixin method for enabling In-Context Editing. We will look more details on the next topic about Experience Builder.

  • store: The store directory contains your Vuex Store files. This directory is optional and you can learn more on this topic from here.

Experience Builder

Let’s take a closer look at how we use Experience Builder feature of CrafterCMS with our NuxtJS application.


In the above example, we have 2 pages: A home page with the root route / and an About page with route /about. Each page contains the in-context editing feature if you open it in preview mode from Studio.



The green pencil active means ICE (In-Context Editing) is enable. Each element within the view which has a green box is enable for editing.


We use @craftercms/experience-builder package to make ICE possibile in CrafterCMS 4. Here is the whole source code for the About page:



<template>

 <v-row>

   <v-col class="text-center">

     <img src="/craftercms.png" alt="CrafterCMS" class="mb-5" />

     <h1

       v-bind="getIce({ model, fieldId: 'title_s' })"

     >

       {{model.title_s}}

     </h1>

   </v-col>

 </v-row>

</template>

 

<script>

import { fetchIsAuthoring, initInContextEditing }  from '@craftercms/experience-builder';

import { getModel } from '../lib/api';

 

export default {

 name: 'AboutPage',

 async asyncData() {

   const model = await getModel('/site/website/about/index.xml');

   return { model };

 },

 async mounted() {

   const isAuthoring = await fetchIsAuthoring();

   if (isAuthoring) {

     initInContextEditing({

       path: this.model.craftercms.path

     });

   }

 }

}

</script>


When users access the page, first of all, we will get the model which is the content of file /site/website/about/index.xml from the Studio site use the SDK getModel() function with the method asyncData.





 async asyncData() {

   const model = await getModel('/site/website/about/index.xml');

   return { model };

 },


Refer to file `lib/api.js` on how we implement getModel() method using the package @craftercms/content.


A sample output of the model could similar to this JavaScript Object:


{                                                                                                                                                                                               
  craftercms: {
    id: 'f2502f10-30a3-4308-6a8c-e79356219b00',
    path: '/site/website/about/index.xml',
    label: 'About',
    contentTypeId: '/page/about',
    dateCreated: '2022-01-25T10:29:08.868Z',
    dateModified: '2022-01-27T07:52:02.106Z',
    sourceMap: {},
    fileName: 'index.xml',
    placeInNav: 'true'
  },
  navLabel: 'About Us',
  title_s: 'About Us'
}



Then we use this model information to update DOM element <h1>:


     <h1

       v-bind="getIce({ model, fieldId: 'title_s' })"

     >

       {{model.title_s}}

     </h1>


If you open the source code of this DOM, the result should be similar to the following:


<h1 

    data-craftercms-model-id="f2502f10-30a3-4308-6a8c-e79356219b00"

    data-craftercms-model-path="/site/website/about/index.xml" 

    data-craftercms-field-id="title_s" 

    data-craftercms-label="About"

>
  About Us
</h1>


v-bind directive is used to reactively inject HTML attributes to the DOM. We also use getIce() that is a mixin method that is defined in `plugins/ice.js`:


import Vue from 'vue';

import { from } from 'rxjs';

import { fetchIsAuthoring, getICEAttributes }  from '@craftercms/experience-builder';

 

Vue.mixin({

 methods: {

   getIce({ model, fieldId, index }) {

     const isAuthoring = from(fetchIsAuthoring());

     return getICEAttributes({ model, fieldId, index, isAuthoring });

   }

 }

});


getICEAttributes() is an exported function from the package @craftercms/expereicen-builder that gets all the needed attributes for the ICE feature.


Finally, we will use the `mounted()` method to enable ICE when the page is loaded with function initInContextEditing():


initInContextEditing({

   path: this.model.craftercms.path

});


CrafterCMS’ Experience Builder (XB) provides a UI layer on top of your applications that enables authors with in-context editing (ICE) for all the model fields defined in the content types of pages and components. CrafterCMS developers must integrate their applications with XB, essentially telling XB what field of the model each element on the view represents. 


While there are more support for React applications, you can still use the XB with a NuxtJS application as in above example.


To learn more about XB, checkout the documentation here.

Create a new site with NuxtJS integration

In the previous session, we create a site from a blueprint that has NuxtJS enabled. So how about working with NuxtJS from scratch? 


Let's continue this session on how we can create a CrafterCMS site with NextJS integration from scratch.


Go back to the Global Menu, Select Create Site with an Empty blueprint.



Input as follows and click Review > Create Site:


  • Site Name: demo

  • Site ID: demo


Now let’s create our `app` folder with a branch new NuxtJS application. Thanks to Create Nuxt App command, creating a new NuxtJS is super easy:


cd {YOUR_STUDIO_DIR}/data/repos/sites/demo/sandbox
yarn create nuxt-app app



While running the command, it will ask for some questions such as project name, language or UI framework and more. For this example, let’s use Vuetify.js as the UI framework to use Material UI.


When completed, go to `app` directory then start NuxtJS in port 3000:



If the application is created successfully, you should see the following screen when browsing http://localhost:3000.



Update Proxy Configuration from demo site in Studio, you will see the same screen while previewing in port 8080:





As the NuxtJS web application is up and previewable within Crafter Studio, you can freely implement more logic, including the integration with CrafterCMS using CrafterCMS SDK and the Experience Builder. Take the reference from the above nuxt-js site source code on how to do it. 


One last thing you must do when modifying a site outside of Studio is to commit the change:

cd {YOUR_SITE_SANDBOX}
git add app
git commit -m "Add NuxtJS application to CrafterCMS site"



Conclusion

In this tutorial, we have introduced how NuxtJS works with CrafterCMS using the CrafterCMS SDK and the Experience Builder.


Are you interested in building Nuxt.js applications on a headless CMS platform? Download the open source CrafterCMS project here. Get started by reading about the Crafter Engine APIs. And check out the Crafter Studio APIs to customize your content authoring experience. For commercial support and training, visit https://craftercms.com.