Building Websites with Hugo & Markdown
In a previous post, I talked about the value in using Markdown to generate course notes. I’ve continued to refine my use of Markdown, and I’m convinced that it’s still the fastest way to generate semi-structured content for my courses1
I’ve also recently started using Hugo to generate websites. Hugo is a static site generator that takes Markdown source files and related assets, and generates a static website from your content. It supports many, many different themes, so you can pick something that works for particular style of content.
Using Hugo in CS 349
I’ve recently moved the CS 349 website to Hugo, and I’m amazed at how functional the site is compared to the older manually-generated site.
Here’s a screenshot of my course home page. There are a large number of elements that aid in navigation, from the generated table-of-contents, to search capabilties and tags across related pages.
Content is also well-formatted. Images are captioned and scaled properly and even source code is highlighted properly based on the target language. The syntax highlighting of the Kotlin code was generated by Hugo; all I had to do in the Markdown source was tag the language for this block.
Creating a Website
The main Hugo website is here: https://gohugo.io
Download and install the Hugo binaries. e.g. to install from Homebrew for Mac).
$ brew install hugo
Use the Quickstart guide to get a basic website up-and-running.
Optionally, find a new theme from the Hugo Themes site. I use the Learn theme for my course websites. The theme determines a lot of your capabilities e.g. table-of-contents and navigation.
hugoto generate your site, and upload it. That’s it!
Once you’ve walked through the setup, you should have a directory structure like this:
. ├── archetypes/ ├── config.toml ├── content/ ├── data/ ├── layouts/ ├── public/ ├── resources/ ├── static/ └── themes/
config.tomlfile contains the configuration for your site e.g. site name, URL and so on. Read the file carefully and make edits as suggested.
Your contents are placed under the
contentsfolder. Hugo will attempt to mirror your folder structure in the table-of-contents. All of your content will be generated and placed here.
staticfolder includes static elements that you want uploaded to your website, which may not normally exist in the contents. e.g. a site icon.
publicfolder is where a generated site is created and ready to upload.
themesfolder contains any themes that you install. Your
config.tomlwill specify the path to the theme that you are using.
- Look under
themes/theme-name/exampleSitefor an example of site contents. There should be folders in that structure, with pages and so on that serve as a demonstration of the syntax you will need to use.
- Use a good Markdown editor to generate your content (I use and recommend Typora).
- The appearance is controlled by the theme, but you can customize CSS in the themes/ folder (e.g. I changed the default font in my theme).
- Use scripts to generate and upload your site. For instance, I have the following three scripts in my www/ folder (the top-level of my website).
build.sh: generates the website
#!/usr/bin/env bash rm -rf public/* hugo -D
test.sh: deploys it to my local machine for testing
#!/usr/bin/env bash open -a Safari.app http://localhost:1313/~cs398/ hugo server -D
upload.sh: uploads to the appropriate location
#!/usr/bin/env bash rsync -var ./public/ email@example.com:public_html --delete
My workflow for editing pages is to
- Open the contents/ folder in my Markdown editor.
./build.sh ; ./test.shto build the site and bring it up in my local web browser.
- Make edits locally and periodically press
Cmd-Sto save changes. The local copy will automatically refresh for a live preview!
- When you’re ready to publish, just run
./build.sh ; ./upload.sh.
No it’s not nearly as precise as LaTeX, but it’s precise-enough, and much faster to publish to the web. ↩︎