Connecting Gridsome to NetlifyCMS

Step by step tutorial

For the last past months, I have been searching for a Headless CMS to connect with a modern Javascript framework like Vue.js to use for my clients.

After a long search, I found the perfect combination for my needs thanks to a static site generator like Gridsome and a headless CMS like NetlifyCMS.

Static site generators have become very popular because they are straightforward to use, and they are based on JavaScript frameworks like Vue.js or React.

A static site generator uses plain text files rather than a database as the content repository and builds HTML files by applying layouts to them.

The generated static site files(HTML, CSS, JS) are delivered to the end-user exactly as they are on the server. There is no server-side language or database.

Headless CMS make easy to access content via RESTful API.

A headless content management system, or headless CMS, is a back-end only content management system (CMS) built from the ground up as a content repository that makes content accessible via a RESTful API for display on any device.

These create a new architectural concept also called JAMstack, which I talk about more in this article, I recommend you read it to be able to better understand the topic we’re going to deal with today.

Today we will use the JAMstack architecture by connecting Gridsome to NetlifyCMS.

What are we going to develop?

We will develop a simple blog with a list of articles and the specific page of the article, to show the basic functions and how to connect the two technologies step by step.

Then it’s up to you to discover all the features.

Requirements

Basic JS knowledge

Basic VueJS knowledge

Basic GraphQL knowledge would be nice (but not necessary)

Set up a repository on Github for this project

Having a Netlify account

Step 1 — Install Gridsome CLI tool

yarn global add @gridsome/cli

or

npm install --global @gridsome/cli

I will be using yarn during this tutorial.

Step 2 — Create a Gridsome project

gridsome create my-blog

once created we need to open the folder so

cd my-blog

now if you want to start a local dev server

gridsome develop

Ps. Now initialize your repo on Github.

Step 3 — Install Gridsome plugins

For our project, we will need two plugins: transformer-remark and source-filesystem.

source-filesystem: it transforms files into content that can be fetched with GraphQL in your components;

it transforms files into content that can be fetched with GraphQL in your components; transformer-remark: it parses and compiles Markdown;

yarn add @gridsome/transformer-remark

and after

yarn add @gridsome/source-filesystem

Step 4 — Setting up the Gridsome config file

As you may have noticed in our folder, there is a file gridsome.config.js , here let’s add this code

module.exports = {

siteName: 'My blog',

plugins: [

{

use: '@gridsome/source-filesystem',

options: {

path: 'articles/**/*.md',

typeName: 'Articles',

remark: {}

}

},

],

transformers: {

remark: {}

}

}

with the path we say where to look for files and with typeName we decide the GraphQL type and template name.

Step 5 — Create a Markdown file

At the same level as the gridsome.config.js file create a folder called articles and inside it let’s create a file called my-first-article.md .

Now in your my-first-article.md file add this



title: My First Article

image:

abstract: |-

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

author: Mario Rossi

date: 2020-01-07T17:43:37.669Z

--- ---title: My First Articleimage: https://source.unsplash.com/random/1 abstract: |-Lorem ipsum dolor sit amet, consectetur adipiscing elit.author: Mario Rossidate: 2020-01-07T17:43:37.669Z--- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Do the same for the second article! (just change the number after random to get a different image)

Ps. be careful with the indentation of the code in this file because it is easy to get an error.

Should look like this

Step 6 — Get the list of articles

Now let’s try to render our articles in the home, but before let’s clean the Default file and inside src/layouts/Default.vue remove everything and add this code

<template>

<div class="layout">

<slot/>

</div>

</template> <static-query>

query {

metadata {

siteName

}

}

</static-query> <style>

body{

background-color: #f4f4f4;

padding: 0;

margin: 0;

} @media screen and (min-width: 992px) {

.container {

width: 60%;

margin: 0 auto;

padding: 30px 0px;

}

}

</style>

Now let’s go Inside src/pages/Index.vue and let’s write

<template>

<Layout>

<div class="container">

<h1>List articles</h1>

<div v-for="article in $page.articles.edges" :key="article.id" class="article d-flex">

<div class="article__img"

:style="{ 'background-image': 'url(' + article.node.image + ')' }"></div>

<div class="article__body">

<g-link :to="article.node.path" class="article__link"></g-link>

<h1 class="article__title">{{article.node.title}}</h1>

<p class="article__abstract">{{article.node.abstract}}</p>

</div>

</div>

</div>

</Layout>

</template> <page-query>

query {

articles: allArticles {

edges {

node {

title

abstract

image

path

}

}

}

}

</page-query> <script>

export default {

metaInfo: {

title: "My blog"

}

};

</script> <style>

.article {

display: flex;

align-items: center;

box-shadow: 5px 5px 11px rgba(0, 0, 0, 0.15);

border-radius: 8px;

position: relative;

margin-top: 50px;

background-color: #fff;

}

@media screen and (max-width: 992px) {

.article {

display: block;

}

}

.article__title {

margin-top: 0;

}

.article__body {

padding: 15px 30px;

}

.article__link {

position: absolute;

top: 0;

right: 0;

left: 0;

bottom: 0;

}

.article__img {

width: 250px;

height: 140px;

background-size: cover;

background-position: center;

border-radius: 8px;

margin-right: 15px;

} @media screen and (max-width: 992px) {

.article__img {

width: 100%;

height: 180px;

}

}

</style>

Step 7 — Create the layout for the page for the single article

Go inside the folder src/templates and create a file Articles.vue and inside src/templates/Articles.vue let’s write

<template>

<Layout>

<div class="articlePage">

<div class="articlePage__img"

:style="{ 'background-image': 'url(' + $page.article.image + ')' }"></div>

<div class="container container--article">

<g-link to="/" class="back"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="arrow-left" class="svg-inline--fa fa-arrow-left fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M257.5 445.1l-22.2 22.2c-9.4 9.4-24.6 9.4-33.9 0L7 273c-9.4-9.4-9.4-24.6 0-33.9L201.4 44.7c9.4-9.4 24.6-9.4 33.9 0l22.2 22.2c9.5 9.5 9.3 25-.4 34.3L136.6 216H424c13.3 0 24 10.7 24 24v32c0 13.3-10.7 24-24 24H136.6l120.5 114.8c9.8 9.3 10 24.8.4 34.3z"></path></svg>Back</g-link>

<h1 class="articlePage__title">{{$page.article.title}}</h1>

<p>{{$page.article.author}}</p>

<p>{{$page.article.date}}</p>

<div v-html="$page.article.content"></div>

</div>

</div>

</Layout>

</template> <page-query>

query ($path: String!) {

article: articles (path: $path) {

title

content

author

image

}

}

</page-query> <script>

export default {

components: {},

metaInfo() {

return {

title: this.$page.article.title

};

}

};

</script> <style>

.container--article {

margin-top: -140px;

background-color: #fff;

border-radius: 8px;

padding: 30px 60px;

margin-bottom: 100px;

}

@media screen and (max-width: 992px) {

.container--article {

padding: 15px 20px;

}

}

.articlePage__img {

width: 100%;

height: 400px;

background-size: cover;

background-position: center;

}

.back {

display: flex;

align-items: center;

color: #333;

text-decoration: none;

}

.svg-inline--fa{

width: 20px;

margin-right: 15px;

color: #333;

}

</style>

If you’ve come this far, you’re doing great, and now you should see the home page with the list of the articles if you run in the terminal gridsome develop

and the page of the single article

Well, this is a lot so far, and we did the most challenging part now we need to set up Netlify CMS and to connect it.

For the next steps, we are going to follow the documentation of NetlifyCMS.

Step 8 — Add NetlifyCMS to our blog

Inside our static folder we need to create a folder admin with two files: index.html and config.yml

The index.html is the entry point for the Netlify CMS admin interface. This means that the users navigate to yoursite.com/admin/ to access it.

Inside it let’s write

<!doctype html>

<html> <head>

<meta charset="utf-8" />

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<title>Content Manager</title>

<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>

</head> <body>

<script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>

</body> </html>

The config.yml defines the backend configurations like the repository options, the folder for the images, the collections for instance.

Inside it let’s add

backend:

name: git-gateway

branch: master # Branch to update (optional; defaults to master) media_folder: "static/uploads"

public_folder: "/uploads" collections:

- name: "articles"

label: "Article"

folder: "articles"

create: true

slug: "{{slug}}"

fields:

- {label: "Title", name: "title", widget: "string"}

- {label: "Abstract", name: "abstract", widget: "text"}

- {label: "Image", name: "image", widget: "image"}

- {label: "Author", name: "author", widget: "string"}

- {label: "Date", name: "date", widget: "datetime"}

- {label: "Body", name: "body", widget: "markdown"}

Ps. Be careful with the indentation and the spaces of the code in this file because it is easy to get an error. The spaces in your code must be exactly like the example above.

Step 9 — Override the index.html with Gridsome

We need to override the base HTML template to add some script required by Netlify CMS, Gridsome has a feature for this and it is called Overriding Index.html.

Now inside the src folder create a file index.html and let’s add this code

<!DOCTYPE html>

<html ${htmlAttrs}>

<head>

${head}

<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>

</head>

<body ${bodyAttrs}>

${app}

${scripts}

<script>

if (window.netlifyIdentity) {

window.netlifyIdentity.on("init", user => {

if (!user) {

window.netlifyIdentity.on("login", () => {

document.location.href = "/admin/";

});

}

});

}

</script>

</body>

</html>

Now everything is ready, and it’s time to push all the work we have done on Github.

Step 9 — Configuration on netlify.com

Go on the Netlify website and do the Signup/Login, once you are inside your dashboard you should see this

Click the button New site from Git, from here you will authorize Netlify to connect to your Github repository.

Click on Github and do the necessary steps to associate a specific repository

Now write gridsome build as Build command and dist as Publish directory and click Deploy Site (wait until it will be deployed).

Click on Identity and after on the button Enable Identity.

Click Setting and usage

Under the Registration preferences select Invite only

Under the Services click the button Enable Git Gateway

Go back to the Identity tab and click the button Invite users, to allow somebody to edit content from the admin section.

Add your email address and you will receive an email, you need to accept the invite, you will choose a password, and now from your-url.com/admin you will be able to Log in, and you will be able to change the content of your blog.

You should see your Netlify CMS like this

Try to create an article or modify an existing one, wait for the deployment and voila your changes will be online.

Now every time you will change something, Netlify automatically will push on Github and will do the deploy.

This is just a starting point, what we have done for the articles obviously can be replicated for anything: projects pages etc.

Now it’s up to you to have fun and create your projects from this code.

You can find the code here on Github, and if you want to take a look at the demo of this tutorial click here.

If you want to know more about these technologies I suggest you look at the Netlify CMS documentation and the Gridsome documentation