DEV Community

Jonathan Reeves
Jonathan Reeves

Posted on • Edited on

Simple Blog Site with Gatsby

Hello everyone,

Quick note: I use terminal and cmd prompt or command line interchangeably throughout this post. Also in case you are not as familiar with using the terminal in the command throughout this post please do not type the $ in with the commands. The $ is just meant to show you that it is a terminal prompt. Any similarities to courses or posts is coincidence. This post has been my own experience with Gatsby and what I went through building the blog site.

I know in my last post I promised I would write a series of posts on the JAMStack for how to create an eCommerce site. But with this post I just want to start small. A lot of people might not be familiar with Gatsby or static site generators so what I want to do is get you going with your own blog site. One where you can post thoughts and tutorials of your own and then also provide the link here on sites like https://dev.to/ so that you can make sure the posts get read.

The Great Gatsby

Gatsby is a free and open source framework based on React that helps developers build blazing fast websites and apps. This is directly from Gatsby's home page at https://www.gatsbyjs.org/. What does Gatsby allow us to do? And why is it so fast?

The Workings of Gatsby

Gatsby allows us, as developers, to use several different ways to get data to our application/website. We can use CMSs, Markdown, or data in the form of JSON or an API even. We can pull data in from anywhere. Write some code and Gatsby will take the code generate a website using HTML, React, and some CSS and allow you to deploy to sites such as GitHub Pages, Netlify, AWS Amplify and Zeit Now to name a few.

Examples:

With Gatsby developers and even non developers that want their own site can finally enjoy the power of the latest web technologies like React. You can even use Webpack and modern JavaScript to build your site. You are able to bring your own data. Gatsby uses a rich data plugin ecosystem that lets you build sites with the data you want. You can pull from one or many different sources such as: from a headless CMS or SaaS, multiple APIs, databases your own file system and more using the power of GraphQL.

Speed of light

Gatsby builds the fastest possible website. Instead of waiting to generate pages when you request them, Gatsby has already pre-built the pages and just lifts them so to speak into a global cloud of servers where they are ready to be delivered instantly to your users wherever they are.

Now that you have a brief introduction to what Gatsby can do let's get started with actually setting up the project.

Where to Start

The first thing that you will want to do in order to work with Gatsby is actually make sure you have nodejs installed. Head over to nodejs.org and click the download button. I usually recommend the lts version. I have circled which one to use in the screen shot below
Alt Text

After you have Nodejs installed you can verify that its been installed by opening up your terminal and typing:

$node -v
Enter fullscreen mode Exit fullscreen mode

Also make sure you have an up-to-date version of npm as well with this command:

$npm -v
Enter fullscreen mode Exit fullscreen mode

At the time of writing this post the versions I have installed are:
Alt Text
If you have YARN installed and would rather use it over npm feel free to replace the commands with the YARN equivalent.

Getting Gatsby

Now that we have the necessary tools available we are going to install Gatsby. To install Gatsby you will run these commands in your terminal.

$npm install -g gatsby gatsby-cli
Enter fullscreen mode Exit fullscreen mode

The commands above will make sure that we are installing the latest versions of both Gatsby and the Gatsby CLI.

Brief pause in the Action

I want to take a second and say that here: https://www.gatsbyjs.org/starters/?v=2 you are able to go and look at a starter template to use for your site. I know we are creating a blog but that doesn't mean that you can't make the site look good by choosing a neat starting template. Be sure to replace the one I chose in the command used in the next section with one you chose. If you didn't find one that you liked feel free to just use the same command I did.

Creating your project

Next we will run the command to bootstrap a new Gatsby project. In your terminal type the following command, remember to replace the url with the starting template of your choice if it's different from mine.

$gatsby new awesome-blog https://github.com/gatsbyjs/gatsby-starter-blog
$cd awesome-blog
$npm i
Enter fullscreen mode Exit fullscreen mode

This will start to generate all the files and folders necessary for the project. As well as install all of the dependencies the project needs. After this finishes run:

gatsby develop
Enter fullscreen mode Exit fullscreen mode

Once the application has started you should be able to view the project on localhost:8000.

Gatsby config file

We are going to create a config file. So here I will open the project in VS Code, you can of course use whichever IDE or text editor you are comfortable with. From within your terminal if you are using VS Code input this command to open the project:

$code .
Enter fullscreen mode Exit fullscreen mode

This command will open the project directly in VS Code at the current directory you are in. If you are using Atom then the command is similar:

$atom .
Enter fullscreen mode Exit fullscreen mode

Next we will create a new file called gatsby.config. Inside the file we will write this:

module.exports = {
  siteMetaData: {
    title: 'My Super Awesome Blog',
    description: 'This blog is my personal blog, I think it's awesome'
  },
  plugins: [
    `gatsby-transformer-remark`,
      {
        resolve: `gatsby-source-filesystem`,
        options: {
          name: `pages`,
          path: `${__dirname}/src/pages`
      }
    }
  ]
} 
Enter fullscreen mode Exit fullscreen mode

Quick note with the plugins section above those are backticks not quotes. Also I wanted to let you know that if you decided to use a different starter kit then you will most likely already have a gatsby.config file. You can modify this if you feel comfortable with doing that. If not just leave it the way that it is or you could just use the simple blog starter kit.

With the config file created we are ready to start adding posts. We can do this by right clicking on the pages directory from within VS Code and typing out the date then the name of the blog post like this 2020-03-16-my-first-blog-post. Make sure this is folder and not a file. This is a directory for your posts. Next we will create an index.md file in this directory. The index.md file will be our actual blog post.Inside of the index.md file we can type:

---
path: "/my-first-blog"
date: "2020-03-16"
title: "My First Blog Post"
tags: ['gatsby', 'blog']
excerpt: "My very first Gatsby Blog Post"
---

Here is the content of my first Gatsby blog. This is really awesome.
Enter fullscreen mode Exit fullscreen mode

Using React

Inside of our pages directory we will need an index.js file. Let's create it now if it doesn't already exist. Inside of the index.js file we will add these lines of code:

import React from 'react';
import { StaticQuery, graphql } from 'gatsby';

const TitleAndDescription = ({data}) => {
  const title = data.site.siteMetadata.title;
  const description = data.site.siteMetadata.description;

  return (
    <div style={{
       display: 'flex',
       flexDirection: 'column',
       alignItems: 'center'
    }}>
      <h2 style={{marginBottom: 0}}>{title}</h2>
      <p style={{
        marginTop: 0,
        opacity: 0.5
      }}>
       {description}
     </p>
    </div>
  )
}

const Header = () => {
  return (
    <StaticQuery
      query={graphql`
        query {
         site {
          siteMetadata {
            title
            description
           }
          }
         }
       `}
        render={data => <TitleAndDescription data={data} />}
    />
  )
}

const Layout = () => {
  return (
    <div>
      <Header />
    </div>
  )
}

export default Layout;
Enter fullscreen mode Exit fullscreen mode

Let's actually refactor this a little bit. Create a new fold in your src directory called components. Then create a new files one called Header.js and we will take all of this:

import React from 'react';
import { StaticQuery, graphql } from 'gatsby';

const TitleAndDescription = ({data}) => {
  const title = data.site.siteMetadata.title;
  const description = data.site.siteMetadata.description;

  return (
    <div style={{
       display: 'flex',
       flexDirection: 'column',
       alignItems: 'center'
    }}>
      <h2 style={{marginBottom: 0}}>{title}</h2>
      <p style={{
        marginTop: 0,
        opacity: 0.5
      }}>
       {description}
     </p>
    </div>
  )
}

export default Header;
Enter fullscreen mode Exit fullscreen mode

and copy it over to the Header.js file. Then remove the two components from our index.js file. Make sure you leave the imports and then after you have removed the components, import the header file:

import Header from '../components/Header';
Enter fullscreen mode Exit fullscreen mode

List of our Posts

We are now going to try to render our list of posts to the page. To do that we need to add some more code to our index.js file. Place this code above our default export statement at the bottom of the page.

export const query = graphql`
  query listOfBlogs {
     allMarkdownRemark(
      sort: {order: ASC, fields: [frontmatter___date]}
    ) {
       edges {
        node {
         frontmatter {
           title
           path
           date
         }
      }
   }
}
`
Enter fullscreen mode Exit fullscreen mode

Next what we want to do is modify our Layout component to accept the data. Let's add that code now.

const Layout = ({data}) => {
  const { edges } = data.allMarkdownRemark
  return (
    <div>
     <Header />
      {edges.map(edge => {
        const {frontmatter} = edge.node;
        return (
         <div key={frontmatter.path}>
          {frontmatter.title}
         </div>
        )
      })}
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

In the above code snippets I added ASC for the order parameter on allMarkdownRemark. You can add DESC if you want to show your latest posts first. I chose ASC because I wanted the order to start with my very first post. This is your site and your blog so you should make it how you want it.

It's All About the Link

So as you've probably noticed you have the title of the post or posts you've made at this point but you can't go into the post to actually read anything. That is because they are not a link. Let's do that now.

// modify the import statement from Gatsby
import { graphql, Link } from 'gatsby';

// next we will wrap our title with the Link tag
<Link to={frontmatter.path}
  {frontmatter.title}
</Link>
Enter fullscreen mode Exit fullscreen mode

Now the titles are links and we can... not go to them. What gives? Why do we get a 404 error? Well we haven't created the routes to those pages yet.

Follow the Route of the 40 Thieves...

So in order to create the route we need to create a file in the root directory. So outside of the src directory where your node_modules folder is create a new file and call it gatsby-node.js. Then inside your src folder let's add a templates folder. Inside the templates folder we will create a file called blogPost.js.

//blogPost.js
import React from 'react';
import { graphql } from 'gatsby';

const Template = (props) => {
  return (
    <div>
     Blog Post! Blog Post! Read All About It!
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode
// gatsby-node.js
const path = require(path);

exports.createPages = (({graphql, actions}) => {
  const { createPage } = actions;

  return new Promise((resolve, reject) => {
    const blogPostTemplate = path.resolve('src/templates/blogPost.js');
    resolve(
     graphql(
       `
       query {
        allMarkdownRemark {
          edges {
           node {
            fronmatter {
              path
            }
           }
          }
        }
      }
     `
   ).then(result => {
     result.data.allMarkdownRemark.edges.forEach(({node}) => {
        const path = node.frontmatter.path
        createPage({
          path, 
          component: blogPostTemplate,
          context: {
            pathSlug: path
          }
         })

         resolve()
        })
      })
 )

})
Enter fullscreen mode Exit fullscreen mode

We will need to rerun gatsby develop command so that the changes we made take effect. Now we are able to click on our title and it will take us to the blog post.

Building the Blog Post Template

We are going to update our template file to actually get our HTML for the blog post. Above our export for Template place this code:

import React from 'react';
import { graphql } from 'gatsby';

const Template = ({data}) => {
  const {markdownRemark} = data;
  const title = markdwonRemark.frontmatter.title;
  const html = markdownRemark.html;
  return (
    <div>
      <div className="blogPost" dangerouslySetInnerHTML={{__html: html}} />
    </div>
  )
}

export const query = graphql`
 query($pathSlug: String!) {
    markdownRemark(frontmatter: { path: {eq: $pathSlug} }) {
      html
      frontmatter {
        title
      }
    }
  }        
`
Enter fullscreen mode Exit fullscreen mode

Moving Forward and Backward

We are now going to add the next and previous links to our blogs so that we can either go to the next one directly from the current post or the previous one as well. We will be updating our gatsby-node.js file.

// in the .then()
const posts = result.data.allMarkdownRemark.edges;
posts.forEach(({node}, index) => {
  const path = node.frontmatter.path;
  createPage({
    path,
    component: blogPostTemplate,
    context: {
      pathSlug: path,
      prev: index === 0 ? null : posts[index - 1].node,
      next: index === (posts.length - 1) ? null : posts[index + 1].node
    }
  })
Enter fullscreen mode Exit fullscreen mode

Make sure the .then() method looks like the above snippet. Now we are going to update our query for allMarkdownRemark to make sure that the order is correct for our previous and next posts.

allMarkdownRemark (
  sort: {order: ASC, fields: [frontmatter___date] }
 ) }
Enter fullscreen mode Exit fullscreen mode

We are now ready to add the links. Let's update the template component

import { graphql, Link } from 'gatsby';

const Template = ({ data, pageContext }) => {
  const {next, prev} = pageContext;
  // under the return add this
 <div style={{marginBottom: '1rem'}}>
  {next && 
    <Link to={next.frontmatter.path>
     Next
    </Link
  }
  {prev &&
    <Link to={prev.frontmatter.path}>
     Previous
    </Link>
  }
 </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Tag You're It

We will now add browsing posts by tag. We will start by adding some templates. In our templates directory lets add tagsIndex.js and tagindex.js.

// tagsIndex.js
import React from 'react';
import { graphql, Link } from 'gatsby';

const TagsTemplate = ({ data }) => {
  return(
    <div>
      <div>
        tags here
      </div>
    </div>
  )
}

export default TagsTemplate;
Enter fullscreen mode Exit fullscreen mode
// tagIndex.js
import React from 'react';
import { graphql, Link } from 'gatsby';

const TagTemplate = ({data}) => {
  return (
    <div>
      <div>
        tags here
      </div>
    </div>
  )
}

export default TagTemplate;
Enter fullscreen mode Exit fullscreen mode

Now we need to update our gatsby-node.js file.

const createTagPages = (createPage, posts) => {
  const tagsIndexTemplate = path.resolve('src/templates/tagsIndex.js);
  const tagIndexTemplate = path.resolve('src/templates/tagIndex.js);

  const postsByTag = {}

  posts.forEach(({node}) => {
    if (node.frontmatter.tags) {
      node.frontmatter.tags) {
        if(!postsByTag[tag]) {
          postsByTag[tag];
        }

        postsByTags[tag].push(node);
      })
    }
  })

  const tags = Object.keys(postsByTag)

  createPage({
    path: '/tags',
    component: tagsIndexTemplate ,
    cointext: {
      tags: tags.sort()
    }
  })


}
Enter fullscreen mode Exit fullscreen mode

Next we will update our .then() method to actually create the pages.

// underneath the posts variable
createTagPages(createPage, posts)

// make sure to add this line in our query
      title
      tags
Enter fullscreen mode Exit fullscreen mode

Restart our gatsby develop and we should now be able to see our tags page at localhost:8000/tags. Next we will update our gatsby-node.js file to iterate over the tags.

// under createPage add this line
tags.forEach(tagName => {
  const posts = postsByTag[tagName];

  createPage({
    path: `/tags/$tagName}`,
    component: tagIndexTemplate,
    context: {
      posts,
      tagName
    }
  })
})
Enter fullscreen mode Exit fullscreen mode

Now lets update our tagTemplate.

const tagTemplate = ({data, pageContext}) => {
  const { posts, tagName } = pageContext;
  return (
    <div>
      <div>
        Posts about {`$[tagName}`}
      </div>
    <div>
      <ul>
        {posts.map((post, index) => {
          return (
           <li key={index}>
             <Link to={post.frontmatter.path}>
               {post.frontmatter.title}
             </Link>
           </li>
          )
        })}
      </ul>
    </div>
  </div>
 )
}
Enter fullscreen mode Exit fullscreen mode

We will now open up the tagsIndex.jsfile and give it a similar treatment.

// tagsIndex.js
const TagsTemplate = ({data, pageContext}) => {
  const { tags } = pageContext;
  return (
    <div>
      <div>
        <ul>
          {tags.map((tagName, index) => {
            return (
              <li key={index}>
                <Link to={`/tags/${tagName}`}>
                  {tagName}
                </Link>
              </li>
            )
          })}
        </ul>
      </div>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

The final thing we are going to do in this section is create a link on the home page to view all posts.

//index.js
//Under our edges mapping put this code
<div>
  <Link to='/tags'>Browse by Tag</Link>
</div>
Enter fullscreen mode Exit fullscreen mode

Pu Pu Pu Push It Real Good

We are finally finished with our blog site. It is now time to push the website to production. We will be using Netlify. We will need to run one command that will bundle all of this code up and make production ready.

gatsby build
Enter fullscreen mode Exit fullscreen mode

Then we can head over to GitHub, if you don't have a GitHub account don't worry it's free. I believe you could also use BitBucket if you are more comfortable doing that. I believe the steps are similar but I'm not 100% on that. From GitHub you can make a new repository name it whatever you want. I will be using my-awesome-blog. Here are the basic steps for pushing to GitHub:

  • visit https://github.com
  • sign up or login
  • create a new repository by clicking the + next to your profile image
  • name your repository
  • follow the below steps to push your code
cd <root of project>
dir //if you are on mac use ls
// make sure you see the src folder in the list
git init
git add .
git commit -m "initial commit"
git remote add origin git@github.com:<YOUR GITHUB USERNAME HERE>/<NAME OF YOUR REPO HERE>.git
git push -u origin master
Enter fullscreen mode Exit fullscreen mode

Now go to netlify.com. Sign up or sign in if you already have an account. If you sign up I would definitely use your GitHub, BitBucket, GitLab etc account to sign up. It will make publishing easier. Then follow these steps

  1. Click on the Git provider button you pushed your code to, if you followed this tutorial it should be GitHub.
  2. Authorize your account.
  3. Select the repo in my case it would be my-awesome-blog.
  4. Select the master branch, should be the only branch you have
  5. We don't need to specify any build commands or the publish directory since we did that already with the gatsby build command*
  6. Click the Deploy site button
  7. After the build has finished you will have a link you can go to that will end with netlify.com. You can share that link with friends and family as the site is now live.

The End

Thanks for reading this tutorial. I hope that it helped you in seeing the power of Gatsby and that it demonstrated its ease of use. Now that you have your own blog site you can blog about anything and everything. Those of you that are proficient with React can modify this site to be more than just a blog. If you wanted to convert this to a portfolio site with your blog attached you definitely could. Please feel free to leave your comments and let me know if you liked this. I am totally up for doing more.

Top comments (6)

Collapse
 
lhebia profile image
Lawrence Hebia

Used this to launch my first blog. Thanks!

Collapse
 
redhoodjt1988 profile image
Jonathan Reeves

No problem glad to help. Would love to read your blog if you send the link.

Collapse
 
lhebia profile image
Lawrence Hebia

I would really appreciate that!
👉🏼 sevenrules.ca/

Thread Thread
 
redhoodjt1988 profile image
Jonathan Reeves

That's awesome. I like the posts. Really awesome hobm I'm glad I was able to help you get that going. You're more than welcome to check out my Gatsby site programmingwithjon.com

Thread Thread
 
lhebia profile image
Lawrence Hebia

Very nice! Loved your thoughts on breaking problems in frameworks out and solving with plain JavaScript - really great way to think when troubleshooting.

Thread Thread
 
redhoodjt1988 profile image
Jonathan Reeves

Thanks. Sorry for the late response. If you ever need anything answered or help with anything I will do what I can to assist you.