Scope:
In this tutorial, we will learn how to set up Gatsby with Contentful CMS and then deploy the application on Netlify for free.
Background:
Prior to this, I had my blog site running on AWS(deployment post) that required extra effort to set up, and publishing content on it was a bit tedious. Moreover, I had a free tier plan that got expired, and the relevant services(EC2 t2.micro & RDS db.t2.micro) were being billed at around a dollar a day.
I wanted to revamp my blog site and improve the content management flow in particular so started looking out for other options and got to know about Static Site Generators and was amazed at how incredibly easy it was to work with them. I chose Gatsby to build the front-end layer of the blog and integrated it with Contentful CMS to fetch data from there.
Setting up Gatsby:
Install Gatsby CLI globally on your machine by running the following command from the terminal.
npm i -g gatsby-cli
To generate a new project run:
gatsby new your-project-name
This will create a new project folder with all of the starter files. Switch to the project directory and run
gatsby develop
This would start the gatsby server on the default port of 8000.
Gatsby Starter
Starters are basically boilerplate code that is maintained by the community to facilitate the development process. We can add another argument to our project setup command that is the URL of the starter that we want to use.
I initialized my project by using this starter and running the following command:
gatsby new gatsby-blog https://github.com/W3Layouts/gatsby-starter-delog
I found the markup, styling, and dark mode feature super cool so went with it to speed things up. I did some customizations and changed the CMS to Contentful which was more powerful. The final site can be found here.
Setting Contentful CMS
A CMS is pretty useful as it offers a nice interface for managing content and exposes APIs to pull data from it.
- Head over to contentful.com and create a free account.
- Create a space for your project content from the sidebar menu.
- Next head to the Content model tab, which could be thought of as schema for your actual content or blog posts. It will have fields like the blog title, description, publishing date, etc.
- Click on the Content model tab to add a content type and click on the Create button.
- Add relevant fields in your model by clicking on the Add Field button. I had added the following fields:
- Save it and head to the Content Tab to create your first post by clicking on the Add Blog Post button.
- Hit the publish button once done and now we can start accessing this data from the Gatsby site.
- Prior to it, go to the Settings dropdown menu and click on the API Keys and generate a new key by clicking on the Add API Key button. Copy the Space ID and Access Token that will be required later.
Gatsby Project Setup:
Project Github link: https://github.com/Asim1996/gastby-blog
In the installed starter project run the following command to install the Contentful plugin:
npm install gatsby-source-contentful@2.3.12
The source plugin is required for pulling content types, entries, and assets into Gatsby from Contentful spaces. Add the plugin to gatsby-config.js file
module.exports = {
siteMetadata: { ... },
plugins: [
{
resolve: 'gatsby-source-contentful',
options: {
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN
},
forceFullSync: true
},
...
]
}
Create .env file in your project root directory and paste the Contentful Space ID and Access Token in it.
Modify your development script in the package.json file to fetch data from the .env file.
"develop": "env-cmd .env gatsby develop"
For fetching all blog posts data the allContentfulBlogPost node would be used in the GraphQL query.
The above query returns the list of all posts available in Contentful which is then passed as props to the Card Component to generate a view for all posts.
Rather than fetching the post body too in the initial index page and passing it as props down the child component, we will be creating dynamic pages with the help of slug content-type defined in our blog schema and adding configurations in the gatsby-node.js file as defined below.
const path = require("path")
// Create blog pages dynamically
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const blogTemplate = path.resolve('./src/templates/blog.js')
const res = await graphql(`
query {
allContentfulBlogPost {
edges {
node {
slug
}
}
}
}
`)
res.data.allContentfulBlogPost.edges.forEach((edge) => {
createPage({
component: blogTemplate,
path: `/blog/${edge.node.slug}`,
context: {
slug: edge.node.slug,
},
})
})}
The above code dynamically generated blog pages basis the markup defined in the template file and the slug that is being fetched from Contentful in the building process of your Gatsby site.
In your project src directory create a new folder named templates and create a file named blog.js in it.
The following code is used to fetch the relevant blog post basis the slug that comes from the context object from the gatsby-node.js file.
...
export const query = graphql`
query($slug: String!) {
contentfulBlogPost(slug: { eq: $slug }) {
title
publishedDate(formatString: "MMMM Do, YYYY")
description
backgroundImage{
title
fluid(maxWidth: 300, maxHeight:200) {
...GatsbyContentfulFluid
}
file{
url
fileName
contentType
}
}
body{
json
}
}
}
`...
The JSX in the file can be modified or styled accordingly basis on the data we now have as props.
To render the Rich Text content(blog post body) install the following package:
npm install @contentful/rich-text-react-renderer
and for syntax highlighting then use the following package:
npm i react-syntax-highlighter
The template file can then be modified to use the above packages and render the content in a more appealing way.
Deploying to Netlify
Push your code on Github(or any other Git provider) and signup for a free account on Netlify. Then, click on the New site from Git button and choose your Git provider and the repository that needs to be deployed. Add your Environment Variables by clicking on the Show advanced button on the deploy settings page.
Click on the Deploy site button that will trigger the deployment process and once it is complete you'll see your site URL. And that's it, a few button clicks and your site is live on the internet.
Optional Setups:
Mapping a custom domain: If you have an existing domain bought from any external Domain Name provider (GoDaddy, BigRock, etc). Head to your domain name provider and create an A record and link Netlify’s load balancer IP with your domain name to complete the entire setup.
Helpful links: Custom Domains, Configure External DNS
Netlify Forms: In your contact form just add the following attributes
<form class="form" name="contact" method="post" data-netlify="true" data-netlify-honeypot="bot-field">
<input type="hidden" name="bot-field" />
<input type="hidden" name="form-name" value="contact" />
Netlify's bots will automatically detect the attribute data-netlify="true" when you deploy your site and process the form for you.
Head to Settings > Forms > Form notifications and receive an email alert anytime a new submission comes through.
Helpful Link: Netlify Forms
Configuring a Netlify build hook: If you make changes to your Contentful post data, you can either trigger a deploy manually from Netlify or generate a Netlify build hook (that you can add to Contentful CMS) to trigger an automatic redeploy of your site.
From the Netlify dashboard, navigate to the "Settings" for your site, choose "Build & deploy", and scroll to "Build hooks".
Click Add build hook that then generates an HTTPS URL that responds to requests by triggering a build and deployment of your site. Copy the URL and navigate back to the Contentful web app. From the Settings choose Webhooks and paste the URL that Netlify provided into the form.
Helpful link : Netlify Build Hook
Adding Disqus to Gatsby: Having a comment section in your blog post can be pretty helpful and that could easily be set up signing up on Disqus. Post that, install the following package:
npm i disqus-react
Add the following config in your template file:
...
const disqusConfig = {
url: `https://404found.tech/${props.data.contentfulBlogPost.slug}`, identifier: `${props.data.contentfulBlogPost.slug}`,
title: props.data.contentfulBlogPost.title,
}
<Disqus.DiscussionEmbed shortname="404found-tech" config={disqusConfig} />
...
Thanks for reading.
Cheers!!
Top comments (0)