I created a custom Hugo template for my personal static website. Everything is hosted in GitHub Pages.
When I launched my personal website back in January, I used a publicly available Hugo theme and tweaked some parts of it without comfortably knowing exactly how Hugo worked, how the theme was structured, and how the CSS was written. However, this month I gave web design another try when my friend asked me to help redesign his static website that was built using Pelican, another static site generator that’s powered by Python instead of Go.
Using Pelican to learn how to build a web template was a very good introduction for me for many reasons:
After finishing the project, which involved going through the exercise of organizing files and customizing HTML fragments/partials and editing CSS, I felt like I was better equiped to build my own website from scratch. I chose to continue with Hugo despite another learning curve because it’s crazy fast, the framework is more flexible (e.g. taxonomy templates), and there were already a lot of good looking themes in GitHub that I could pick apart.
Unlike my first time building my Hugo website when I used someone else’s theme, I came up with the majority of my design in one night. I thought purely in terms of aesthetics and UX: the journey of visiting my homepage, scrolling down to highlights, clicking into a showcased project, and exploring other projects. It included a few epiphanies, some small trial and error, and my recent experiences glossing over web design when building my friend’s website. I also reacted very quickly to what I wanted to tweak or scrap, since I knew exactly what I wanted and didn’t want. I felt more confident about this project since I was expressing myself. :')
In retrospect, I think these colors came from my memory of traveling with one of my closest friends to Austria. Being broke college grads, we literally Googled “SFO to Europe” and spontaneously booked a 5-day vacation to the destination with the cheapest flight. It still ranks among my best trips of all time. One of my favorite art places there was the colorful Hundertwasser Haus in Vienna.
One of my proudest parts of this website was animating the title page using CSS. I actually stumbled upon this trick when I was considering adding D3.js throughout my website but didn’t like how I would have to import additional scripts. I looked more into animating images with HTML/CSS and found this article that has a CSS animation tutorial. The post mentioned Lemonade’s Giveback website, which looked so amazing and so simple (or at least not as hard as you think) to implement.
For the base image, I drew a one-line icon in Illustrator and exported it as an SVG. That standalone SVG file contains an embedded CSS, which I altered with the animation trick. This probably took me 2 or 3 hours to make, from starting with an empty artboard in Illustrator to getting a self-drawing art palette on my home page.
Writing every partial template, the main CSS, and restructuring files to build a custom template was pretty challenging, even though I had fresh experience with Pelican. While concepts were similar, implementation were pretty different. Hugo’s documentation was actually confusing, given it’s higher complexity and flexibility. I wasn’t aware of Hugo-specific concepts, so sometimes I didn’t understand what I just read or what I was missing to get something to work.
The most challenging thing I faced to actually getting the pages to build due to the way Hugo recognizes page types. If I had understood Leaf and Branch Bundles from the start, I would not have wasted so many hours guessing different things and wondering if my Hugo version was somehow incorrect. Since I did not know that there was a difference between
_index.md (branch/landing page/has children) and
index.md (leaf/post/no children), I thought Hugo was inconsistently building pages. Usually, only the home page would build, but if I manually saved any other page, it would no longer throw a 404 error. 1 forum post saved me by referring to the bundle explanation.
After grasping the idea of bundles, I was quickly able to figure out how to better organize my content based on other people’s comments in the forum. I settled with this structure below. I had 1 Branch folder and
_index.md for my 3 tabs (About, Showcase, Projects), and my individual posts live under the
projects Branch. Organizing my files this way allowed me to fully feel in control of my theme, since it was catered specifically for me.
. ├── config.toml ├── archetypes │ └── default.md -- use as guide for new posts ├── content │ └── _general -- general content for website │ └── about │ └── _index_.md │ └── projects -- holds projects (1 project per folder) │ └── _index_.md │ └── project-1 │ └── index_.md │ └── picture.png │ └── project-2 │ └── index_.md │ └── showcase │ └── _index_.md │ └── _index_.md └── themes └── ifcolorful -- make edits to template
Once I got at least 1 landing page (Hugo’s
list.html) working, everything became a lot easier. I could reuse of a lot of the CSS, partials/HTML, and other code. As I got more than 50% of the website done, I relied less on looking up examples of HTML/CSS implementation from existing Hugo templates.
Instead of typing in the actual command for building Hugo, I used a MakeFile to speed up my productivity. Now I just have to type
make hugo, which is much easier to remember when I decide to make some design tweaks several months down the road.
#!/usr/bin/make hugo: hugo server -D git: git add -A git commit -m "$m" git push origin main
The final step was to push the changes and have GitHub build and deploy the static content. I followed my boyfriend’s tutorial to push changes to a private repository while hosting in a separate public repository. It was not as scary as I expected and took 2 hours to set up my GitHub Actions that would deploy to GitHub Pages. Hosting my website like this is completely free!