14 KiB
aliases | author | date | linktitle | toc | menu | next | prev | title | weight | |||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Spencer Lyon | 2014-03-21 | Hosting on GitHub | true |
|
/tutorials/installing-on-mac | /tutorials/creating-a-new-theme | Hosting on GitHub Pages | 10 |
This tutorial was contributed by Spencer Lyon.
Introduction
Many Hugo users have expressed interest in seeing a tutorial for how to set up a blog that is generated by Hugo and hosted on GitHub Pages. This tutorial will do just that. We only require that the reader has Hugo installed correctly and is comfortable with git and GitHub.
During this tutorial, I will walk you through the main steps I took to create an example blog available at http://spencerlyon2.github.io/hugo_gh_blog. The source code for this blog is on GitHub. Readers are encouraged to download the example repository and follow along.
Find a Home for Your Files
As our goal is to host a website using GitHub Pages, it is natural for us to host the content of the page in a GitHub repository. Thus, the first step is to either create a new repository on GitHub or create a new directory within an existing repository where the content of the website will live. To do this, I created the repository spencerlyon2/hugo_gh_blog.
Create the Blog
Write a config.yaml
File
The very first step in creating a new Hugo site is to write the config file. This config file is important for at least two reasons: (1) this is where site-wide settings (like the websites baseurl
) go, and (2) the config file dictates to some extent how Hugo will generate the website. For the example website I created a file config.yaml
with the following contents
---
contentdir: "content"
layoutdir: "layouts"
publishdir: "public"
indexes:
category: "categories"
baseurl: "http://spencerlyon2.github.io/hugo_gh_blog"
title: "Hugo Blog Template for GitHub Pages"
canonifyurls: true
...
Caveat: Hugo's former default of
canonifyurls: true
has been changed tofalse
since this tutorial has written. Please make sure you manually addcanonifyurls: true
to yourconfig.yaml
if you are using Spencer's https://github.com/spencerlyon2/hugo_gh_blog for this tutorial, or you will run into problems such as the CSS files not loading.
See "Canonicalization: Caveat" on the "Extras: URLs page" for more information.
Define Structure of Website
Hugo assumes that you organize the content of your site in a meaningful way and uses the same structure to render the website. Notice that we have the line contentdir: "content"
in our configuration file. This means that all the actual content of the website should be placed somewhere within a folder named content
. Hugo treats all directories in content
as sections. For our example we only need one section: a place to hold our blog posts. So we created two new folders:
▾ <root>/
▾ content/
▾ posts/
Create HTML Templates
The next step is to define the look and feel of your new website. Because Hugo will generate the site using HTML templates written by the user (you), this step is very subjective. I will merely present one possible theme that could be used to generate a blog. I decided to base the example project on a Jekyll theme called Lanyon. The Lanyon theme is pure CSS and a slightly modified version of the CSS is in the /static/css
directory of the example repository. If you are following along, you should grab the static
folder from the example repository and put it alongside the content
folder you just created.
Because there are so many files needed to fully compose a complete website, I will not be able to go through each of them here. I will, however, show what the directory structure should look like when all is said and done:
▾ <root>/
▾ content/
▾ posts/
<blog posts>.md
▾ static/
▾ css/
lanyon.css
poole.css
▾ layouts/
▾ partials/
<templates to be used in other files>.html
▾ posts/
li.html
single.html
summary.html
▾ indexes/
category.html
indexes.html
posts.html
index.html
README.md
Each of the files in the example repository is well commented with a description of what the file as a whole does as well as an explanation of all major components in the file. If you are new to web development and/or Hugo, I encourage you to search through these files to get a feel for how Hugo templates work and how the site is stitched together.
Add Some Content
The final step in creating the blog is to add some actual blog posts. To do this, simply create one Markdown file (with extension .md
) for each new blog post. At the top of each file you should include a metadata section that tells Hugo some things about the post (see docs). For example, consider the yaml metadata section from the top of the file /content/posts/newest.md
from the example repository:
---
title: "Just another sample post"
date: "2014-03-29"
description: "This should be a more useful description"
categories:
- "hugo"
- "fun"
- "test"
---
The keys set in this section are the mandatory title
and date
as well as the optional description
and categories
. Each of these items is used throughout the templates found in the /layouts
directory and gives Hugo information about the post from other pages in the website.
Configure git
Workflow
Once the site is set up and working properly, we need to push it to the correct branch of a GitHub repository so the website can be served through GitHub Pages. There are many ways to do this. Here I will show the workflow I currently use to manage my websites that are hosted through GitHub Pages.
GitHub Pages will serve up a website for any repository that has a branch called gh-pages
with a valid index.html
file at that branch's root. A typical workflow might be to keep the content of a website on the master
branch of a repository and the generated website on the gh-pages
branch. This provides nice separation between input and output, but can be very tedious to work with. As a workaround, we will use the git subtree
family of commands to have the public
directory (or whatever publishdir
is set to in your config.yaml
) mirror the root of the gh-pages
branch of the repository. This will allow us to do all our work on the master
branch, run Hugo to have the site output into the public
directory, and then push that directory directly to the correct place for GitHub Pages to serve our site.
To get this properly set up, we will execute a series of commands at the terminal. I will include all of them in one place here for easy copy and paste, and will explain what each line does via comments. Note that this is to be run from the <root>
directory (wherever the content
and layout
folders of your Hugo project live). Also note that you will need to change the commands that have the example repository GitHub address so that they point to your repo.
# Create a new orphand branch (no commit history) named gh-pages
git checkout --orphan gh-pages
# Unstage all files
git rm --cached $(git ls-files)
# Grab one file from the master branch so we can make a commit
git checkout master README.md
# Add and commit that file
git add .
git commit -m "INIT: initial commit on gh-pages branch"
# Push to remote gh-pages branch
git push origin gh-pages
# Return to master branch
git checkout master
# Remove the public folder to make room for the gh-pages subtree
rm -rf public
# Add the gh-pages branch of the repository. It will look like a folder named public
git subtree add --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages --squash
# Pull down the file we just committed. This helps avoid merge conflicts
git subtree pull --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages
# Run hugo. Generated site will be placed in public directory (or omit -t ThemeName if you're not using a theme)
hugo -t ThemeName
# Add everything
git add -A
# Commit and push to master
git commit -m "Updating site" && git push origin master
# Push the public subtree to the gh-pages branch
git subtree push --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages
After executing these commands and waiting for the GitHub servers to update, the website we just created was live at http://spencerlyon2.github.io/hugo_gh_blog.
deploy.sh
Now, as you add new posts to your blog, you will follow steps that look something like the following:
- Create the Markdown source for the new post within the
content/posts
directory - Preview your work by running Hugo in server mode with
hugo server
- Run Hugo not in server mode so that the generated urls will be correct for the website
- Add and commit the new post in
master
branch - Push the
master
branch - Push the public subtree to the remote
gh-pages
branch
The first two items in the previous list are simply a way to conveniently preview your content as you write. This is a dynamic and fairly streamlined process. All the remaining items, however, are the same every time you want to add new content to the website. To make this repetitive process easier, I have adapted a script from the source repository for the Chimer Arts & Maker Space website that is highlighted in the Hugo Showcase. The script lives in a file called deploy.sh
and has the following contents:
Note:
The first command hugo
assumes you are running with all the default settings.
To use a theme, make sure to specify it with -t ThemeName
instead (or include the theme in the config file).
hugo -t ThemeName
To build all draft posts (If you only have drafts, no site will be generated)
hugo --buildDrafts
Deploy.sh:
#!/bin/bash
echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"
# Build the project.
hugo
# Add changes to git.
git add -A
# Commit changes.
msg="rebuilding site `date`"
if [ $# -eq 1 ]
then msg="$1"
fi
git commit -m "$msg"
# Push source and build repos.
git push origin master
git subtree push --prefix=public git@github.com:spencerlyon2/hugo_gh_blog.git gh-pages
Now I can replace the last four items from our workflow list with a single command bash deploy.sh
. This script accepts as an optional argument the commit message that git should use when committing your changes. If you wish to include a custom commit message, do so by putting it quotes after calling bash on the script: bash deploy.sh "<my commit msg>"
. If you choose not to specify the commit message, one will be generated for you using the current time.
Configure git
Workflow, the Alternate Way
The above uses a git subtree
to deploy to Gits gh-pages
branch. This works great, but with one drawback: It requires the generated content to be committed to the source branch.
There's another approach:
- Set up your Hugo-site on
master
- Create an orphaned
gh-pages
branch. (See here for more information.) - Follow the instructions below.
So, assuming you have your gh-pages
set up, and master
has a commit with some content you want to publish:
# Fetch the deployment script into the root of your source tree, make it executable.
wget https://github.com/X1011/git-directory-deploy/raw/master/deploy.sh && chmod +x deploy.sh
# For setting it up to build to a folder other than "dist", see the options in deploy.sh.
# Build the site to /dist.
hugo -d dist
# Run the deploy.sh script installed above.
./deploy.sh
This will use the last commit as a base for the commit message to the gh-pages
branch.
For more information about the deployment script, see this README.
Hosting Personal/Organization Pages
As mentioned in this GitHub's article, besides project pages, you may also want to host a user/organization page. Here are the key differences:
- You must use the
username.github.io
naming scheme.- Content from the
master
branch will be used to build and publish your GitHub Pages site.
It becomes much simpler in that case: we'll create two separate repos, one for Hugo's content, and a git submodule with the public
folder's content in it.
Step by step:
- Create on GitHub
<your-project>-hugo
repository (it will host Hugo's content) - Create on GitHub
<username>.github.io
repository (it will host thepublic
folder: the static website) git clone <<your-project>-hugo-url> && cd <your-project>-hugo
- Make your website work locally (
hugo server -t <yourtheme>
) - Once you are happy with the results, Ctrl+C (kill server) and
rm -rf public
(don't worry, it can always be regenerated withhugo -t <yourtheme>
) git submodule add git@github.com:<username>/<username>.github.io.git public
- Almost done: add a
deploy.sh
script to help you (and make it executable:chmod +x deploy.sh
):
#!/bin/bash
echo -e "\033[0;32mDeploying updates to GitHub...\033[0m"
# Build the project.
hugo # if using a theme, replace by `hugo -t <yourtheme>`
# Go To Public folder
cd public
# Add changes to git.
git add -A
# Commit changes.
msg="rebuilding site `date`"
if [ $# -eq 1 ]
then msg="$1"
fi
git commit -m "$msg"
# Push source and build repos.
git push origin master
# Come Back
cd ..
./deploy.sh "Your optional commit message"
to send changes to<username>.github.io
(careful, you may also want to commit changes on the<your-project>-hugo
repo).
That's it! Your personal page is running at http://username.github.io/ (after up to 10 minutes delay).
Conclusion
Hopefully this tutorial helped you get your website off its feet and out into the open! If you have any further questions, feel free to contact the community through the discussion forum.