How I made this custom static site blog using only Go Web Templates and TOML

02/12/2020

Hello, on this first post of my blog I wanted to discuss how it was put together. This site is a static site made using a variety of tools but most importantly Go Web Templates and TOML markup. My goal was to build a minimal blog that allows me to easily make posts.

Static site?

I chose to use a static site for a variety of reasons. The primary reason is that there are a lot good free hosting options so it would be easy to put the site up. By being a static site, my blog is just a folder with HTML content being served. This greatly simplifies / removes the need for complex infrastructure like databases or back end API layers. I went out of my way to reduce the amount of HTTP requests needed to load a page of this blog. I wanted this site to be fast and accessible. I am making an effort to be as semantic as possible with the HTML tags I use. This way, screen readers or other accessibility tools should be able to parse the content. I also wanted to make a site that could be read by people who use a command line web browser like w3m. All of this isn't to say that I don't appreciate and love some of the more flashy things you can now do on the web. In fact, I spent a good portion of my career focusing on building just that. I am a big fan of canvas and wanted to add a flashy canvas background, but I felt it wasn't suited to the purpose of this site. You might find some posts to three.js or canvas projects I work on from this blog in the future; however.

Why not use an existing static site generator?

There are many existing great static site generators that I could have used rather than building my own. I have used Hugo in the past and since it uses Go web templates it is very similar to what I ended up making. In Hugo you write your content with markdown and provide a metadata section at the top of the markdown file called front matter. Hugo lets you choose which config language you want to use for the front matter either YAML, TOML, or JSON. While it is a nice feature that it lets you pick which language you prefer, I asked myself what if it was ALL in the chosen front matter language. I first tried JSON and quickly remembered that JSON was never intended for human beings to read or write in it, it is a wire format for machines. I then went straight to TOML.

TOML

I had used TOML for config files in the past on projects as well as for my front matter language in Hugo but never for long form text content. At first I wasn't too sure but once I found that it had a multi line string I felt it was more suited for a blog than JSON. Another perk of TOML is that it can be easily serialized into a Go struct, which is handy when rendering Go templates. By using multi line strings I am able to write naturally and not worry about escaping characters. I also found a syntax plugin for vim. There is one exception to this however and that is HTML inside of a multi line string in TOML.

Go Templates and Embedded HTML

In the process of building this blog I gained an appreciation for how powerful go templates are. Multiple templates can be stored in a memory at a time, allowing templates to reference one another. This allows for almost all of the layout to be handled entirely in the template code. I chose the file extension tmpl and to my surprise vim continued to apply HTML syntax highlighting to the file despite not having the HTML extension. To render the templates I created a struct to represent the model of the data and in some cases nested those structs in one another. Most of the structs only correspond to a single template but the root or home struct does have two templates. The first is the home page of the site and the second is the RSS feed. As a user of RSS readers in the past I never actually looked into the format before making this site. I was pleasantly surprised at how simple RSS is. As I mentioned earlier, I did hit a snag with Go templates while building this site, embedding HTML into a multi line string. When executing a template Go will escape HTML unless told to do otherwise. In order to instruct it to not do this you need to add a new function to the templates FuncMap. This function will tell the template to render the content as HTML not as a string and preserve the nested content. You can read more about adding functions to the FuncMap here.

Adding htmlSafe function to the FuncMap

htmlSafe := func(html string) template.HTML {
	return template.HTML(html)
}
...
tmpl, err := template.New("home.tmpl").Funcs(template.FuncMap{
	"htmlSafe": htmlSafe,
}).ParseFiles(
	"templates/home.tmpl",
	"templates/header.tmpl",
	"templates/footer.tmpl",
)

Organization

The site is organized in a single GitHub repo including both the rendered content and the tools and data to render the content. At the root of the repo you will file the rendered HTML. GitHub pages was a convenient hosting solution since I use GitHub anyway to host my repositories. You will also find the CNAME file in the root that tells GitHub to forward adamjrichardson.com requests to this repo. Inside the tools folder things are a little more interesting. I have created a folder for the templates and one for the TOML files called "data". Assets are also stored inside the tools folder and are copied up to the root of the repo at build time. The main.go file contains all of the logic for loading the templates and the data and rendering the output. The program will go inside the data folder and grab a few hard coded TOMLs for the home page and about page. After that it will grab all of the posts inside the posts directory and sort them by their dates. Finally it renders the output and saves it to the root of the repo. I created a simple Makefile that has two targets clean and build. After writing a posts TOML file I simply run make clean build in the tools folder and it will generate the new site. All that is left is to push the code up to GitHub.

Style and CSS

The style of the site is very spartan and minimal. I was influenced by Fabian Sanglard's site as well as Brad Fitz's site. Originally I had a dark background with light text but after consulting some designer friends they talked me out of this and I switched to a light background. I used coolors.co to find the hue I wanted and then I adjusted the brightness until I had a color that I liked. I did notice that it looks very different on some less color accurate monitors. While I do love mono spaced fonts I wanted to have some contrast between the body text and the code snippets so I opted to go sans-serif. It Trebuchet on Windows and Helvetica on macOS. Another tip that my designer friends gave me was to space out the text more than I originally had it to improve readability.

How well does it work?

So far this is working out pretty good for me. My goal wasn't to build the next Static Site Generator to be used by the masses but to build a custom one that worked for me. I think it is doing the job well. I don't have any repetition of HTML or CSS. Running the make command after writing a post is a piece of cake. If I need to add a new template section I can just write it in the tmpl file and then edit the model to have the property.