Hugo, Through Design
Using theme design to learn Hugo better
I would play with site design every day, from when I got home from work until passing out after 2AM. My workspace was a corner desk with a large 22" flat screen CRT and a Mac mini, with barely enough memory to drive the display. My chair constantly hit the railing of my bed, which barely fit in the room. The screen made it feel like the room was bigger. What I worked on made it feel like anything was good enough.
People used what I made and that was rewarding. MacMod, a website dedicated to modifying Apple hardware, was where I spent most of my efforts. I’d occasionally spend time on my own site, but much less often. The MacMod user base was niche, meaning the users we had were few but loyal. I was “staff”, meaning I could contribute and make changes that I saw fit. It meant freedom in making MacMod work, and look, better.
Over time I lost motivation in working on websites. It wasn’t MacMod or a lack of time that caused it. Internet Explorer’s awful lack of CSS and element compatibility is to blame. I spent more time trying to figure out how to support all of the CSS components and browser elements that Internet Explorer decided to not handle well, even across versions. It was maddening. I could make one small pixel change and everything would fall apart in Internet Explorer. Hours could be wasted trying to figure it out, just to realize your fix now makes it not work in FireFox. Conditions could be thrown at the browsers, but there was a point it became not fun to even think about.
I have done light website work for jobs, and only once where “design” could be considered. I made a small dashboard site to render Hadoop cluster data when I was at LinkedIn. It was the first project I was tasked to do when I joined the Hadoop SRE team (formerly GridOps). Using jQuery and Bootstrap, I made it so users could add new clusters and configure the dashboard to show capacity information. That dashboard hasn’t been used in years, but I think back to how nice it was to have a dashboard be a single-purpose tool.
A Change
My personal website was stagnant. I didn’t update the content at all. The copyright rightfully sat unchanged for a couple years, from the last time I made a change. Even then, what I did do was automate deployments using CircleCI. It wasn’t design. The site had a theme I found and modified to my own tastes. I didn’t pay attention to how the content rendered. What I did do was remove branding, change the favicon to my picture, and add some social media links. It was barely a business card of a site, but it worked.
I wanted a change. I wanted to do something. The time I spent wasn’t really time, but just the bare minimum. So, with some actual effort and a bit of motivation that I haven’t had for site design in a long time, I took on a redesign of this site. With that, I wanted to do the “full” design. Not use a theme someone else made, but one of my own. I would understand how everything appeared and what didn’t. Full design.
My site uses Hugo, a static site generator written in Go. I can deploy the site to Github Pages for free, along with using my personal domain name (adamwhitlock.com). Hugo has a local server mode, which makes it quick to test changes and see what breaks. However I need more than just Hugo. I’d need to figure out what I wanted the CSS to look like, what templates I’d need to create, and how to make the Markdown content appear the way I wanted. This seemed fun!
Bringing up Bulma
I used Bootstrap, a popular CSS and Javascript library, many years ago for that dashboard project at LinkedIn. I wanted to try something new, not only as a challenge but to also see what’s changed in the last six years. After searching for “CSS frameworks”, and thinking about what I would want for my site, I came up with a list of criteria that the framework needed to meet:
- “Does this framework require a lot of Javascript?”
- “Does this framework have good mobile design considerations?”
- “Does this framework support Sass and compile down into smaller assets?”"
After consideration, I found that Bulma met my expectations. It met all of the criteria while coming with good documentation that someone stepping back into site design would need.
Bulma provides a lot of built-in tools that make design easy. One of which is the grid framework that uses columns, based on Flexbox from Mozilla. Columns can be added, always have equal width relative to each other, and you can use as many columns as you want. To span across columns and use individual sizes, you can specify values like is-two-thirds
or is-half
and achieve some quick layout wins. The navbar that comes with Bulma is amazing. You can pin it to the top or bottom of a site, specify additional navigation elements like drop-down menus, and with only one Javascript function enables a mobile navigation drop-down menu.
Becoming Sass-ier with CSS
To be upfront, I didn’t understand what Sass did until I started working with Bulma. I saw Sass files in project directories and knew they were related to design, but didn’t bother understanding how. My days in CSS and web design were many years ago, back when CSS Zen Garden was in its heyday. If you wanted to talk about which <SPAN>
or <DIV>
class to use with Wordpress or Joomla, I could probably answer it. However, that was more than a lifetime ago and cool things came out, including tools meant to answer some of the big design problems I always found myself facing (centering a div, anyone?). One of the biggest being able to reuse or declare design elements within CSS.
Learning how Sass works to compile CSS opened my eyes up to what I had been missing with CSS during the last 10+ years. Sass allows for variables to be declared in source .sass files, which are they compiled into browser-ready CSS. This meant that elements I’d have to carefully comment, search, or separate into separate CSS files could be replaced with a single value! Sass also allows for writing nested statements. Values like table-border-22
don’t need to exist with a complex map documented somewhere when a code needs to be updated. Instead, you can simply replace $blue
or $table-border-color-main
to meet conditions. This is really what CSS should have baked-in the whole time, but creating a language to compile down to CSS is the right way of doing it.
When you use nesting within a Sass file, you can declare a nested structure and expect CSS to be written for every value within. An example would be:
li
font:
family: san-serif
weight: bold
Items nested under the li
element would have full CSS generated for them, as such:
li {
font-family: san-serif;
font-weight: bold;
}
Beyond reducing the amount of code duplication within CSS, it allows for declarative CSS use whenever possible. Compile what’s used, but don’t repeat yourself when writing the first time.
When using Hugo, you can compile Sass files to be compiled into CSS files. Hugo will also use the generated CSS files as source for our compiled page. I’ve provided an example showing how Hugo, in a /layouts/partials/header.html
retrieves a base Sass file (.scss
) and executes a compile operation on it. If the .scss
contains imports, such as @import "path/to/sass
, it will compile all relative path imports as well. In addition to compiling the CSS, using Hugo pipes you can minify the output! It’s no longer a separate step, which may seem obvious to frontend designers but to me is amazing after being away for so long.
{{- /* css */}}
{{ $sass := resources.Get "css/base/base.scss" | resources.ExecuteAsTemplate "style.scss" . }}
{{ $css_output := $sass | resources.ToCSS | minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $css_output.Permalink }}" integrity="{{ $css_output.Data.Integrity }}">
Laying it Out
There’s a Theme
Skeleton & Layout
Using Hugo’s built-in theme skeleton, I ran hugo new theme huey
and created a new theme named “Huey”. The basic structure was good enough to start with, yet when you look at Hugo’s documentation the directory structure is missing one critical component: assets. Assets store what is used by Hugo pipes to build sites, so if you are using something like Sass (which I am) you will need to store your CSS source files in assets
. The static
directory, which the hugo
command creates, is only meant for files ready to be used. Knowing this difference will mean understanding how to use
Reduce, Reuse, and Shortcode with Hugo
Hugo uses Markdown for writing content, which doesn’t provide an easy way to format text beyond what’s provided. Markdown’s biggest strength is portability, so its not fair to say that this is a workaround. If you intend on something being a page header or having a horizontal rule, it will be there regardless where you move your content. Swapping out themes will mean that your content will have a similar layout, regardless what theme you use. There is always an exception, which in this case is if your Hugo theme uses shortcodes.
Shortcodes are a way of working around the limitations of basic Hugo layout and Markdown, where you can insert your own code snippet wherever you define it in a Markdown document. The problem I ran into was that I wanted to center images, where there’s not a magic “Markdown center” markup that makes this happen. Instead, I found an existing Hugo shortcode that centers text and images. I brought into the theme, the only real component I didn’t bother writing 100% from scratch, to make centering happening. Hugo has built-in shortcodes as well, such as using a gist
from Github or highlighting text.
Creating shortcodes is an eventual happy path when working with Hugo. There’s only so much that the built-in shortcodes and Markdown formatting can provide. Theme author’s account for many possibilities, such as page layouts or sections, without making it too complex. With a shortcode, you can extend a theme without needing to touch the design layout. Shortcodes live within the /layouts/shortcodes
directory as individual HTML files. This means the moment you start using shortcodes you will need to keep track of them, and likely validate them, when building your site. With the theme I was working with, I added them to the theme directory to make it easy for myself and users of the theme. I also added documentation in the README.md of the theme to make it accessible.
Page Bundles are Great
While writing content for my site, I found that I could bundle content within directories. I don’t like the idea of content spilling out into a main directory or tracking what images end up in /static/images/whateveriforgotinamedthis.png
. It creates clutter and also makes it harder to reference content. I began using Hugo page bundles to keep all of my content for a blog post or page in a single folder. One caveat is that you have to create a page using index.md
as the main page name. For people used to writing web pages, this isn’t that far of a stretch since the default page for any folder would be index
regardless. Here is an example of a page bundle layout:
hugo-site
├── content/
│ ├── posts/
│ │ ├── new_post/
│ │ │ ├── header.png
│ │ │ ├── image1.png
│ │ │ └── index.md
│ │ ├── _index.md
...
Something I added to my theme was the ability to take pictures named header
and automatically post them as the header image for the post. This lowers the amount of time necessary to specify images. If I don’t want to use a header image, I can simply ignore using it. Additional files can be referenced relative to the post itself. When writing markdown it’s not necessary to use the /static
path but you can use the relative path (such as image1.png
in the example). Alt text can also be used. Here’s a better example showing the image reference with alt text:
![Image alt text](image1.png)
What’s Next for Huey?
I’m going to keep working on Huey, though development velocity will decrease as it becomes more of what I expect it to look like. I never take the tact that a creative endeavor is ever complete, but that it can live on in new works. If I find myself wanting to deviate too far from Huey, I’ll create a fork or new project.
Huey is available to the public, using the MIT open source license. If you want to use Huey, please clone or fork the theme repository at github.com/alloydwhitlock/huey. Follow instructions in README.md on how to install the theme in your own project. Contributing to Huey is encouraged, with instructions also located in the README.md. Feedback is appreciated too, however pull requests for what are considered “bugs” are even more appreciated.