DEV Community

Lucien Bénié
Lucien Bénié

Posted on

How To Build a Static Website With Contentful and Gridsome

Original article can be found here

I never took the time to properly build my website even though I am a Senior Software Developer Engineer. I started to look at some technologies in 2018 and 2019, I found some amazing projects (nuxt, vuepress, etc...) but I never did finish my personal website.

That trend came to an end when I found Gridsome. It has everything I was looking for. It's BYOD (bring your data), uses a single source of truth (GraphQL) and powered by Vue.js. Of course, it has more features, check them out at gridsome.org.

P.S. I built this website using this tutorial and I felt the need to write an article about it to help others do the same thing :)

Tools

To build our static website we will be using three main tools:

  • Gridsome for our static website, powered by Vue.js.
  • Contentful to host our data.
  • Netlify to host our static web site.

Layout the foundation for our content

The first step is to setup up Contentful where we will store our content on their cloud. If you don't have an account on Contentful, then create one.
Once you're provisioned with an account, log in and we will prepare our space with content models suited for a Blog and an example content.

To do this, simply click on the top left menu and click on the button to create a new space. You can opt to create an example space with a Blog example. For the sake of this tutorial that's what we'll do. Name your space and let's grab our API key and Space ID.

To grab our API key, click on the button 'Use the API'. From there you will be able to grab your Space ID Content and Delivery API access token. The environment should be master by default. We will need these to integrate with Gridsome.

Scaffold our static website

To install Gridsome, you can use Yarn or NPM. It is recommended to use the former.

  1. Install Gridsome CLI tool
  • Using YARN
yarn global add @gridsome/cli
Enter fullscreen mode Exit fullscreen mode
  • Using NPM
npm install --global @gridsome/cli
Enter fullscreen mode Exit fullscreen mode
  1. Create our Gridsome project
gridsome create my-first-blog
cd my-first-blog
yarn install # or if you use npm, npm install
yarn develop # or if you use npm, npm run develop
Enter fullscreen mode Exit fullscreen mode

Now that our project has been scaffolded, let's dive in!

Add our Data into our website

Now that we are up and running, we can add our data from Contentful to our static site Gridsome. We have to configure Gridsome with the contentful plugin.

First, let's add these modules:

yarn add @gridsome/source-contentful markdown-it
Enter fullscreen mode Exit fullscreen mode

Then let's create our .env file at the root of the project to hold our contentful Space ID and Access Token values.

Make sure you never push that file on a repository. If that ever happens, anyone could use the API key and do harmful things to your data.

It is highly recommended to add your .env file to your .gitignore file.

CTF_SPACE_ID="<YOUR_CONTENTFUL_SPACE_ID>"
CTF_ACCESS_TOKEN="<YOUR_CONTENTFUL_ACCESS_TOKEN>"
Enter fullscreen mode Exit fullscreen mode

Now, let's head to our gridsome.config.js file and add this configuration.

module.exports = {
  siteName: 'Gridsome',
  plugins: [
    {
      use: '@gridsome/source-contentful',
      space: process.env.CTF_SPACE_ID,
      accessToken: process.env.CTF_ACCESS_TOKEN,
      host: 'cdn.contentful.com',
      environment: 'master',
      typeName: 'Contentful',
    },
  ],
  templates: {
    ContentfulBlog: '/blog/:slug',
  },
}
Enter fullscreen mode Exit fullscreen mode

By default Gridsome is already setup to read data from our .env file.

We officially have linked our data to our static website. We can now build a page where we can list all of our blog posts. Let's create a file pages/Blog.vue and add this code snippet below:

<template>
  <Layout>
    <section v-if="$page">
      <ul>
        <li v-for="{ node } in $page.posts.edges" :key="node.id">
          <h2>
            <g-link :to="node.path">{{ node.title }}</g-link>
          </h2>
          <div>
            <span>{{ node.date }}</span>
            <span> &middot; </span>
            <span>{{ node.timeToRead }} min read</span>
          </div>
          <div>
            {{ node.excerpt }}
          </div>
          <div>
            <g-link :to="node.path">Read More</g-link>
          </div>
        </li>
      </ul>
      <pager
        v-if="$page.posts.pageInfo.totalPages > 1"
        :info="$page.posts.pageInfo"
      />
    </section>
  </Layout>
</template>

<page-query>
  query Posts($page: Int) { posts: allContentfulBlogPost(sortBy: "date", order:
  DESC, perPage: 3, page: $page) @paginate { totalCount pageInfo { totalPages
  currentPage } edges { node { id title timeToRead excerpt path date(format:
  "MMMM D, Y") } } } }
</page-query>

<script>
  import { Pager } from 'gridsome'

  export default {
    metaInfo: {
      title: 'Blog',
    },
    components: {
      Pager,
    },
  }
</script>
Enter fullscreen mode Exit fullscreen mode

We are now ready to add a link to our new Blog page. Let's head to layouts/Default.vue and add the following after the /about link:

<g-link to="/blog">Blog</g-link>
Enter fullscreen mode Exit fullscreen mode

Now we can access our /blog route, but all of the links on that page will forward us to the 404 page. To fix that we'll need to create a template for our contentful blog post. Create a file templates/ContentfulBlogPost.vue.

The filename must match the collection name in the GraphQL environment. If you entered a different typeName in the gridsome.config.js for the contentful plugin. For example, ContentfulDataBlogPost.vue if you chose contentfulData as the typeName.

<template>
  <Layout>
    <div>
      <h1>
        {{ $page.post.title }}
      </h1>
      <g-image :src="$page.post.heroImage.file.url">
      <div v-html="content" />
    </div>
  </Layout>
</template>

<page-query>
  query Post($path: String!) {
    post: contentfulBlogPost(path: $path) {
      title,
      heroImage {
        file {
          url
        }
      },
      body
    }
  }
</page-query>

<script>
import MarkdownIt from 'markdown-it'

export default {
  metaInfo() {
    return {
      title: this.$page.post.title,
    }
  },
  computed: {
    content() {
      const md = new MarkdownIt()

      return md.render(this.$page.post.body)
    },
  },
}
</script>
Enter fullscreen mode Exit fullscreen mode

With this, we should be able to navigate to /blog and select a blog post and navigate to /blog/:slug seamlessly.

Hosting our static website

As said previously, we will be using Netlify to deploy our static website. If you don't have an account head over netlify and create one. When provisioned with your account, click the button 'New Site from Git'. Follow the instructions and we won't need to specify a command we will create a netlify.toml file with our configuration. Click on the 'Advanced' tab and we will be able to create environment variables on Netlify. Here you'll set the values from your .env file because we cannot version control that file. That way Netlify will know to pass our static website variables to connect to contentful.

Let's head back to our editor and let's create the netlify.toml file at the root of the project.

[build]
  publish = "dist"
  command = "gridsome build"
Enter fullscreen mode Exit fullscreen mode

Let's push our code to GitHub and Netlify will take care of the rest for us!

Preview our website

Hurray! We're done, our static website has been configured and deployed. If you wish to preview your website Netlify provides a URL and you can pass that around to friends so they can see you're awesome work!

Top comments (5)

Collapse
 
ffxsam profile image
Sam Hulick

Just a correction:

The proper format for the config file is:

  plugins: [
    {
      use: '@gridsome/source-contentful',
      options: {
        space: 'SPACE_ID',
        accessToken: 'TOKEN',
        host: 'cdn.contentful.com',
        environment: 'master',
        typeName: 'Contentful'
      }
    }
  ],
Enter fullscreen mode Exit fullscreen mode
Collapse
 
ffxsam profile image
Sam Hulick • Edited

Also, this tutorial is maybe missing some steps. When I run gridsome develop after following the steps, I get:

Error: A content type for the ContentfulBlog template does not exist.

Collapse
 
dev23jjl profile image
James

Hi @ffxsam, that would be because you haven't defined a content type that the tutorial uses in Contentful. You need to define a blog post content type in Contentful and depending on what you name that content type, you may need to change some of the query related code.

Thread Thread
 
ffxsam profile image
Sam Hulick

Thanks, James! It's been ages since I've messed with this, and we actually wound up using a different CMS solution. But I'll come back to your post if I ever decide to go this route again.

Thread Thread
 
dev23jjl profile image
James

You're welcome. I understand the switching from one CMS to the next. I've tried numerous, but I think I'm going to stick with Sanity instead of using Contentful.