Staying static with Nuxt: Implementing Netlify CMS
Tags: nuxt, netlify, cms, headless
Published: 2020-07-26 22:18:07

### Nuxt v2.13
If you haven't heard of nuxt yet and you're a vue developer, where have you been?

As of Nuxt v2.13.0, a new config option for Nuxt has been introduced;

```js
target: 'static'
```

I won't go into detail about what this means for your static sites as Sébastien has already done a great job in the article [here](https://nuxtjs.org/blog/going-full-static), but this is one step closer to allowing us to have a full offering while being completely serverless.

After reading this post, I thought about what would be a great way to fully test this new build. Luckily at the company I work for, [RCCO (shamless plug)](https://rcco.uk), we have been looking at solutions to allow us to post new job openings for the non-devs without having to manually create PR and merging them.

After doing some research I found that Netlify, who we are already hosting our site on, actually have a great solution for this in the terms of [NetlifyCMS](https://github.com/netlify/netlify-cms). I had read about this a while back but the project was still very early in development and didn't offer quite enough in comparison to some of the competitors at the time, namely [Storyblok](https://www.storyblok.com/), however some time has passed, many more commits added and it now has everything we need.

# Implementation

The implementation of this already has a great tutorial [here](https://www.netlifycms.org/docs/nuxt/) but this hasn't been updated to take advantage of the new `target: static` that Nuxt now offers.

We are going to implement NetlifyCMS into our application and then display the data on our website using @nuxt/content.

### Prerequisites

This is going to assume you already have a project created and know the general points of Vue/Nuxt, if you're looking for some resources on a complete getting started, use the search above as there's some fantastic tutorials on getting started. Once you've done that make sure to come back to this one.

I'm also going to reference sections on the Netlify documentation as there's no point creating an echo chamber that is just repeating the same information.

### Getting started

To get started you need to first add the NetlifyCMS page to your Nuxt application, this is done by making an admin folder inside your `static` folder with the file `index.html`. Inside this html file, copy and paste the following code [(check here for the latest version)](https://www.netlifycms.org/docs/nuxt/#add-the-netlify-cms-files-to-nuxt);

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Content Manager</title>
    <!-- Include the script that enables Netlify Identity on this page. -->
    <script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
  </head>
  <body>
    <!-- Include the script that builds the page and powers Netlify CMS -->
    <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
  </body>
</html>
```

Now create the config file that is used for creating the fields needed for your post. So create `config.yml` inside the same admin folder. Below is a basic version of the one we have implemented;

```yaml
backend:
  name: git-gateway
  branch: master

media_folder: static/img
public_folder: /img

collections:
  - name: 'careers'
    label: 'Careers'
    format: 'json'
    folder: 'content/careers'
    create: true
    slug: '{{slug}}'
    fields:
      - { label: 'Title', name: 'title', widget: 'string' }
      - { label: 'Start', name: 'start', widget: 'string' }
      - { label: 'Salary', name: 'salary', widget: 'string' }
      - { label: 'Summary', name: 'summary', widget: 'string' }
      - { label: 'Perks', name: 'perks', widget: 'string' }
      - { label: 'Type', name: 'type', widget: 'select', options: ['Full time', 'Part time', 'Remote'] }
      - { label: 'Description', name: 'description', widget: 'markdown' }
```

For the full configuration options, check out the [documentation here](https://www.netlifycms.org/docs/configuration-options/)

Now we need to create the area that we have stated for NetlifyCMS to push our content to, for this we are going to use the brand new [@nuxt/content module](https://content.nuxtjs.org/).


### Nuxt Content

This is a new module from Nuxt that allows us to fetch our content and then manipulate it _through a MongoDB like API_. What's great about this is that it means we can use a lot of advanced functions such as [where](https://content.nuxtjs.org/fetching#wherequery) and [sortBy](https://content.nuxtjs.org/fetching#sortbykey-direction) - We're not going to use these in this tutorial but keep them in mind for your own implementation. 

Follow the installation instructions detailed on the @nuxt/content documentation found [here](https://content.nuxtjs.org/installation).

All we need to do is specify to NetlifyCMS to place the content into our new content folder and then Nuxt will take care of the rest. For our use case we have called the folder `careers`.

### Netlify Authentication

Now follow the section on the NetlifyCMS documentation that talks about enabling their Identity service to allow for signup/login, [found here](https://www.netlifycms.org/docs/nuxt/#authenticating-with-netlify-identity). 

I enabled the Google login service to make this even easier (Netlify, you are too good to us).

Once that is done, push all the changes live and navigate to `${your_site}/admin`, click sign up and create a new post. 

### Pulling your posts

Once you have added your content and NetlifyCMS has committed the post to master, pull latest and check `content/careers`. We are going to use this data for the rest of the tutorial so make sure this is working first before continuing. 

Now we have a post created, we need to tell Nuxt about it, this is done using the `nuxtServerInit` action that is created in `store/index.js`. 

```js
export const state = () => ({
  careers: [],
})

export const mutations = {
  setCareers: (state, list) => (state.careers = list),
}

export const actions = {
  async nuxtServerInit({ commit }, { $content }) {
    const careers = await $content('careers').fetch()

    await commit('setCareers', careers)
  },
}
```

This is using the @nuxt/content module to add all our posts to the store for ease of use. Now Nuxt knows about our career posts we can use the data to display on the website.

### The beauty in Nuxt

Now that we have given Nuxt the information it needs to find where our posts are, the magic of `target: static` fully comes into affect. Before the issue of using the `nuxt generate` command was that it couldn't handle dynamic urls as it didn't know what content was needed to create these pages. Now being _fully static_ nuxt runs a crawler on build and one of the areas it checks is the `nuxtServerInit` to see what we are looking for [(Read more here)](https://nuxtjs.org/blog/going-full-static#crawler-integrated). 

The NetlifyCMS continues here about implementing this into your site more, but I'm assuming now you have this data available you can handle it. It also has a great section about using [markdown](https://www.netlifycms.org/docs/nuxt/#rendering-markdown-with-nuxtjsmarkdownit) which paired with the new [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography) plugin creates a fancy CMS page editor with ease.

You can also handle error pages by adding a page in the `layouts` folder called `error.vue` and then adding the following to your `nuxt.config.js`

```js
  generate: {
    fallback: '404.html',
  },
```

An example of this is with our [implementation here](https://rcco.uk/careers/error), have a play with the blocks, it was built with [matter.js](https://github.com/liabru/matter-js)

### Final thoughts

Nuxt and NetlifyCMS can be used to create something that only a couple of years ago was a huge job involving multiple teams working together. It's a very exciting time to be a Front-End developer (Well for me anyway).

Thanks to the Nuxt team for creating such a great application and NetlifyCMS for making my life incredibly easy. Also thanks to all the contributors that help projects like these continue to thrive.

If you want me to continue about creating the dynamic page and then using the data let me know and I'll check my schedule for openings. 

#### Edit History
27/07/2020 - Updated to use @nuxt/content and removed un-needed script in index.vue head