Using Hugo data files
As part of migrating to Hugo I discovered that I could use YAML (or TOML or JSON) files to store data in that could be used when building the site. This comes in quite handy and can be leveraged to build dynamic content easily.
I had some Ruby code in Nanoc that would generate a list of GitHub repositories
on the site (which you can find here). Hugo doesn’t have any support
for these things so I modified my script to generate YAML files in the
data directory. Original repositories are stored in data/github/originals
and forks I’ve got are stored in data/github/forks. Then using the Hugo
data construct I can access them via the built-in template data paths
$.Site.Data.github.forks and $.Site.Data.github.originals, as demonstrated
below. This is a semi-manual process as you have to run the Ruby script before
generating your site content; since my GitHub repository list doesn’t change all
that often this isn’t a big deal but it would be easy enough to run this script
as part of a script that does the full site generation before publishing
the content.
The bits that make it work
The script
The Ruby code that generates the data lives in scripts/:
require 'net/https'
require 'json'
require 'yaml'
require 'fileutils'
USERID = "youruserid"
# Expects two lines: username, and password
AUTH_FILE = "/path/to/github/auth/textfile"
DATA_DIR = "/path/to/hugo/site/data/github"
api_url = "https://api.github.com/users/#{USERID}/repos?per_page=1000"
url = URI.parse(api_url)
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
req = Net::HTTP::Get.new(url.request_uri)
f = File.open(AUTH_FILE)
username = f.gets.chomp
password = f.gets.chomp
f.close
req.basic_auth(username, password)
response = http.request(req)
repositories = JSON.parse(response.body)
FileUtils.mkdir_p(DATA_DIR)
repositories.map do |repository|
output_directory = "#{DATA_DIR}/#{repository['fork'] ? 'forks' : 'originals'}"
FileUtils.mkdir_p(output_directory)
filename = "#{output_directory}/#{repository['name']}.yaml"
puts "Writing #{filename}"
File.open(filename, 'w') do |f|
f.puts repository.to_yaml
end
end
The template for /code
This file resides at layouts/section/code.html:
{% raw %}
{{ template "meta/header.html" }}
<h2>Code</h2>
<h3>Original Projects</h3>
<ul class="repositories">
{{ range $.Site.Data.github.originals }}
{{ partial "repository.html" . }}
{{ end }}
</ul>
<h3>Forks of things</h3>
<ul class="repositories">
{{ range $.Site.Data.github.forks }}
{{ partial "repository.html" . }}
{{ end }}
</ul>
{{ template "meta/footer.html" }}
{% endraw %}
The partial for a repository
This file resides at layouts/partials/repository.html:
<li>
<a class='{{ if eq .fork true }}fork{{ else }}original{{ end }}'
href="{{ .html_url }}">{{ .name }}</a>
— {{ .description }}
</li>