Mario Leone

Deploying a React App to GitHub Pages

Published August 07, 2020

Around the same time that quarantine started in earnest in March of this year, I was lucky enough to be invited to join a new Dungeons and Dragons campaign.

The Dungeon Master is one I've run games with before, and his adventures are always intricate webs of mystery featuring a wide array of characters. Of course, I jumped at the chance. I worked with another player to create twin Pallid Elves named Letheryl and Llyrethe and have been having a blast exploring Wildemount every week since.

At first, I managed Letheryl on a simple Google Doc. That gave me great portability and ease of editing, and honestly was perfectly sufficient. But soon after we started, I got that familiar urge to build something. Thus the first iteration of my character sheet webpage was born.

The first page (hosted at dnd.marioleone.me) was a single index.html file, plus an index.css file to make it prettier. I used GitHub's excellent hosting capability, GitHub Pages, to expose the website to the world, and configured a Route53 rule on AWS (my domain host of choice) to direct the domain to it.

Before long though, I wanted to grow the page beyond what simple HTML would offer. At the same time, I wanted to expand my own frontend knowledge - my technical experience is almost entirely backend - and React caught my eye. I considered Angular and Vue, but I liked React's focus on minimalism. In time, I got most of the quantitative parts of Letheryl's character sheet converted, and was ready to get the new version launched.

As a static page, there was no reason I couldn't continue to use GitHub Pages. However, whereas the original page was HTML that GitHub could automatically parse and deploy, the new React-based version required a build step before it could be similarly interpretted. Enter GitHub Actions.

GitHub Actions are GitHub's CI/CD automation solution. Like Jenkins or TravisCI (with which I have plenty of experience), GitHub Actions allow users to execute scripts on common triggers, like pushing to a GitHub branch or opening a pull request.

I already knew that my webpage could be built locally with the right environment configured:

$ npm install
$ npm run build

I also knew that installing Node and executing NPM commands within a GitHub Actions was a common task:

name: Build React App

on:
  push:
    branches: [master]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Install Node
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install Node packages
        run: npm install
      - name: Build page
        run: npm run build

The only unknown then was getting the built artifact (a build directory containing browser-compatible HTML) pushed into my repository. I chose to push it to a separate gh-pages branch for two reasons:

So the only thing left was to create a deploy step in my workflow, as such:

- name: Deploy page
        run: |
          mv build docs
          cp CNAME docs
          git config --local user.email "${{ secrets.EMAIL }}"
          git config --local user.name "mleone10"
          git add -A
          git commit -m "Updating site"
          git push -f "https://${{ env.GITHUB_ACTOR }}:${{ secrets.GITHUB_TOKEN }}@github.com/mleone10/dnd-site.git" HEAD:gh-pages

Some explaination is in order:

All together then, the following was placed within my repo's master branch at .github/workflows/build.yaml:

name: Deploy React App

on:
  push:
    branches: [master]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Install Node
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: Install Node packages
        run: npm install
      - name: Build page
        run: npm run build
      - name: Deploy page
        run: |
          mv build docs
          cp CNAME docs
          git config --local user.email "${{ secrets.EMAIL }}"
          git config --local user.name "mleone10"
          git add -A
          git commit -m "Updating site"
          git push -f "https://${{ env.GITHUB_ACTOR }}:${{ secrets.GITHUB_TOKEN }}@github.com/mleone10/dnd-site.git" HEAD:gh-pages

And there you have it! Automatic React builds on pushes to the master branch with zero third-party dependencies. That's a total success in my book.

I hope this was a helpful guide through the process of automatically deploying a React app to GitHub Pages. Find the project's full source code here.

Until next time,
- Mario


← Back to Timeline