Deploying a hugo-based website on GitHub user pages

To host a site on GitHub user pages, its contents should be located on master branch of the reposotory username.github.io. A convenient solution would be to store the source code and the site together. I’ve googled two schemes. The common starting point is a locally functionining website, created with blogdown in RStudio (Hugo, Academic theme).

1. Solution with subtrees

The first solution with subtrees occurred simple enough for me, with my little knowledge of git. But later I’ve followed the second, more organized solution.

One repository with two branches:

  • username.github.io:
    • source — source code + public folder contents;
    • master — web-version (only public folder contents).

Web version is pushed to remote repository with git subtree push command.

Main disadvantage of this solution — source branch contains publiс folder.

In a blog by Anatoliy (@tolikcode) there is an easy to follow setup description. A deployment process can be automated with a script, suggested by Jente Hidskes. Here I only outline the steps in case I will have to reproduce them later.

Setup

  1. Initialize an empty git repository and commit something unimportant to master, e.g. README.md. Later I’ve learned that there is a way to make empty commit.
git init
git add README.md
git commit -m "initial commit on master"
  1. Create an orphan source branch for source code. Remove public folder and commit everything.
git checkout --orphan source
rm -rf public ## removes public!!!
git add .
git commit -m "initial commit on source branch"
  1. Push everything
git remote add origin git@github.com:username/username.github.io.git
git push origin master
git push origin source
  1. Add master to public folder as subtree.
git subtree add --prefix=public git@github.com:username/username.github.io.git master --squash

workflow

  1. Make changes to website in RStudio. Get real-time live preview with this command:
blogdown:::serve_site()

By default, live preview renders everything to public folder, including drafts.

  1. Generate web-version.

Stop live preview, reloading R session or by servr::daemon_stop("number, shown by blogdown:::serve_site()").

blogdown::hugo_build()

Commit changes of the source code to source branch.

git add -A
git commit -m "update"
git push origin source
  1. Publish the updated website to master using subtree push.
git subtree push --prefix=public https://github.com/tolikcode/tolikcode.github.io.git master

Afterwards the website can be accessed from GitHub user pages http://username.github.io/.

2. Solution based on submodules

The second submodule-based solution is described in Hugo documentation. At first I could not understand it, but after this video about submodules I worked out how to set up this.

Two repositories:

  • username-src:

    • master — source code.
  • username.github.io:

    • master — web version (only public folder contents). this repository is added as a submodule to public folder of the username-src repository.

Advantage of this solution — clean history for source code and web version.

Deployment is automated with a script deploy.sh.

Setup

  1. Generate a web version of the site in the project folder.
hugo -t hugo-academic # If using other theme edit the command to `hugo -t <YOURTHEME>`
  1. Initiailze a git repository in public sub-folder and push everything.
cd public
git init
git remote add origin git@github.com:username/username.github.io.git
git add .
git commit -m "initial commit of website"
git push -u origin master
  1. Go to the project folder and totally remove public folder.
cd ..
rm -rf public
  1. Initialize git repository in the project folder. Add public to .gitignore.
git init
git remote add origin git@github.com:username/username-src.git
echo "public" >> .gitignore
git add .
git commit -m "initial commit of source code"
git push -u origin master
  1. Connect a repository with web version as a submodule to publicfolder.
git submodule add -b master git@github.com varmara/varmara.github.io.git
git add .
git commit -m 'added public as a submodule'
git push origin master

Workflow

  1. Work on website in RStudio. All changes can be previewed.
blogdown:::serve_site()

Сайт будет сгенерирован в public, но не спешите его в таком виде отправлять на гитхаб: предпросмотр рендерит в т.ч. черновики. By default, live preview renders everything to public folder, including drafts.

All source code changes can be commited to username-src.

  1. When time has come to update, generate web-version.

Stop live preview, reloading R session or by servr::daemon_stop("number, shown by blogdown:::serve_site()"). Then execute a script deploy.sh, which automatically removes outdated contents of public folder, generates website and commits it to username.github.io.

#!/bin/bash

# a script for easy site deploymend from submodule
# make it executable with chmod +x deploy.sh

# Set the English locale for the `date` command.
export LC_TIME=en_US.UTF-8

# The commit message.
MESSAGE="Site rebuild $(date)"

echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"

# Remove old files in public
pushd public
git rm -rf *
popd

# Build the project.
hugo -t hugo-academic # if using a theme, replace with `hugo -t <YOURTHEME>`

# Go To Public folder
cd public

# Add changes to git.
git add .

# Commit changes.
msg="rebuilding site `date`"
if [ $# -eq 1 ]
  then MESSAGE="$1"
fi
git commit -m "$MESSAGE"

# Push source and build repos.
git push origin master

# Come Back up to the Project Root
cd ..

That’s all. An updated website can be accessed from GitHub user pages at http://username.github.io/.