Set up a blog with Gatsby, GitHub pages and GitHub actions
April 27, 2020
DISCLAIMER: This tutorial requires a bit of knowledge working with Git, and GitHub pages.
This is my first post on my new blog! How exciting! Creating this blog was an interesting process for me since I decided to use Gatsby for it. While I had created a gatsby plugin before, I hadn’t actually built anything with gatsby. Starting this new blog was an opportunity to change that.
For my setup, I decided to start off with hosting the blog on GitHub pages. GitHub actions made sense as the perfect tool for continuous deployment of the site, which also happened to be the first time I am using GitHub actions.
After a couple of hours spent figuring out how to properly setup everything, I finally had the blog live and running at xkojimedia.github.io with a minimal template.
Here I would go over how I was able to setup everything.
What is Gatsby and why should I be using it?
Quoting from their site,
Gatsby is a blazing fast modern site generator for React.
That covers the basic cases where you would want to use Gatsby. However, given the rich plugin ecosystem that is available to, and created by the Gatsby community, you can use Gatsby for a whole lot more use cases, like a blog, ecommerce platformm, etc. It is also built with the best practices in mind for the best user experience, including optional offline support for PWAs.
The development experience while working with Gatsby is also great. There are several starter repos to help get you started quickly using Gatsby. The one I would be using is gatsby-starter-blog. I chose it since it is one of the most popular starters for creating blogs with Gatsby.
Setting things up
First, make sure that you have the latest version of node installed (Gatsby aims to support any node version that hasn’t reached it’s End of Life status, but it is always safer to just use the latest version and not have to check if your node version is too old).
Run node -v
in a terminal to see which version of Node.js you have.
node -v
v12.16.2
Next, install the gatsby CLI package globally on your machine, to enable you run gatsby commands.
npm install -g gatsby-cli
Once gatsby-cli is installed, create a new gatsby project using the gatsby-starter-blog starter, and call it whatever you would like. For the sake of this tutorial, we would call it my-blog.
gatsby new my-blog https://github.com/gatsbyjs/gatsby-starter-blog
This would create a my-blog directory with the contents of the gatsby-starter-blog repo and install the dependencies.
Note: It removes the .git directory from the new project, so the project isn’t a repository pointing to the starter. So no need for you to look for that.
Once the process is completed, you can cd
into the new directory and run npm run develop
(yarn develop
) or gatsby develop
. I would recommend running npm run develop
(or yarn develop
using yarn) since this would use the local version of gatsby installed in the project, as opposed to using the globally installed gatsby command. This helps avoid issues with different versions of the gatsby binary used in different projects, so each project uses the gatsby version specific to the project.
Note: The starter comes with both
package-lock.json
andyarn.lock
files. I assume this is to give users the option to choose between yarn and npm. I would recommend choosing one of the two package managers early on, and delete the lock file for the other package manager, to avoid confusion later in the future.
Running the develop script would compile the assets for the site, and watch the files for changes (Gatsby uses webpack underneath for bundling). At this point, open http://localhost:8000 to see the blog.
Easy! Now you have a minimal blog setup that actually works. You can make changes to any of the .md files in content/blog
directory, and you should see the changes reflected on the site. For further details on how to customize the blog, that is beyond the scope of this post. You can go through the README file that comes with the project, and also checkout the Gatsby docs.
Setting up GitHub Pages
GitHub allows you setup user, organization and project sites. For project sites, you can choose to serve the files from the /docs
folder of the repo of the project, the master
branch or the gh-pages
branch of your project repo. For user/organization sites, you only have the options of serving the public files from the master
or gh-pages
branch of a repo. You would need to create a repo called <user>.github.io
I chose to host the blog as an organization site with the files served from the master
branch of the repo. For the gatsby project, the files being served are stored in the public
directory after building the project. That is the part we would need in the github pages repo. We would need to have a repo for the project, and copy over the public
content into the github pages repo.
Now initialize the git repo in the project if you haven’t already done that already (using git init
), commit and push that into GitHub. Also create the user or organization site. Let’s assume the username is blogger. You would create a repo called blogger.github.io
. Build the project using yarn build
and copy the contents of the /public
directory into the blogger.github.io
repo and commit it. If all goes well, you should be able to see the site live at https://blogger.github.io URL. That’s a milestone! 🎉
Next thing we need to do is setup automatically copying the public assets into the blogger.github.io
repo.
Continuous delivery using GitHub Actions
GitHub actions is a new workflow automation tool provided by GitHub. It provides similar functionality available in CI/CD tools like Travis CI, appveyor, circle CI, etc. I would be using it since it is a free automation tool and integrates well with GitHub in a seamless and easy way.
We would create a GitHub action workflow that:
- checks out the repository in a workflow runner
- installs the node modules
- builds the package
- copies the public assets into the
blogger.github.io
repo
We’d create the workflow in .github/workflows/pages.yml
with the following content:
name: GitHub Pages
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: yarn
- run: |
git config --global user.email "<your-email-address>"
git config --global user.name "<your-name>"
- run: yarn deploy
env:
PA_TOKEN: ${{ secrets.PA_TOKEN }}
CI: true
There are a number of things going on here, so let’s break it down.
First we name the workflow as GitHub Pages
.
We specify that the workflow should be run whenever any commit is pushed to the master
branch.
A build
job is specified to run on the latest ubuntu VM with the following steps:
- uses the Checkout GitHub action to checkout the repo in the workflow
- uses the Setup Node.js environment GitHub action to get the workflow environment setup for Node.js using the latest node 12 version.
- run
yarn
to install the node modules - configure git to be able to push to the
blogger.github.io
repo - run
yarn deploy
script (which we would define later) which will build and deploy the project to theblogger.github.io
repo. SpecifyPA_TOKEN
environment variable that would be used by thedeploy
script to authenticate pushing to the repo. ThePA_TOKEN
is your personal access token with permission to write to theblogger.github.io
repo. To create a personal access token, go to your tokens settings page and select therepo
scope. After creating the personal access token, set the token as thePA_TOKEN
secret in the project repo by going to the repoSettings -> Secrets -> Add a new secret
. Now you can access the secret in the workflow using${{ secrets.PA_TOKEN }}
. More information about secrets in workflows can be found here.
For the deploy script, we would use the gh-pages npm package to push the github pages assets into the blogger.github.io
repo using gh-pages -d public -b master -r "https://<your-username>:[email protected]/blogger/blogger.github.io.git"
. This command specifies the public
directory as the source of the github pages, specifies the master
branch, and specifies the remote repo as https://<your-username>:[email protected]/blogger/blogger.github.io.git
. The URL specifies the GitHub HTTP URL along with the username and password used for the authentication of the git operations. You specify your username and the PA_TOKEN
variable replaces your password. You should never use your actual password in automation scripts. Always make use of access tokens that have the scope you need for that script.
Your deploy script in the package.json
file would look something like this:
{
...
"scripts": {
...
"deploy": "gatsby build && gh-pages -d public -b master -r \"https://blogger:[email protected]/blogger/blogger.github.io.git\""
}
}
That’s it! Now you push your changes to GitHub, your GitHub action workflow should pick up your changes and run the workflow. You can find the running GitHub actions in the Actions menu in the project repo.
Once the action workflow is completed, you should see the new public assets in the blogger.github.io
repo.
Conclusion
For a simple blog, Gatsby works well with GitHub Pages for hosting and GitHub actions for automating the workflow. For more dynamic content and sites, you would need some other hosting platform as GitHub Pages handles hosting static pages. However, you can still make use of Gatsby and GitHub actions for more dynamic sites.
Did you find this useful? Do you think there are better approaches to take, or questions? You can reach out to me on twitter @imolorhe.
Write about what you learn. It pushes you to understand topics better.
Sometimes the gaps in your knowledge only become clear when you try explaining things to others. It's OK if no one reads what you write. You get a lot out of just doing it for you.
@addyosmani