Welcome to the new and improved version of my blog! In this article I will discuss how I rebuilt this blog from the ground up.
Around five years ago I decided to make a blog, and like many others that came before me I decided to use a Static Site Generator. Unfortunately, I ended up spending more time setting up the blog than actually writing anything.
Static Site Generators
I was very intrigued when I first heard about Static Site Generators. The idea of using plain text Markdown files to generate HTML files sounded great to me. I had played around with WordPress in the past, but I found it to be very slow and bloated. I also tried Blogger, but I liked the idea of being in complete control of my content.
I looked at all the Static Site Generators available at the time and I settled on Hugo. What I liked about Hugo was that it was a single binary file, which meant that I did not have to fiddle around with a billion dependencies.
I browsed through Hugo's templates and found a nice one for a blog and I was able to generate a test article fairly quickly. The future was looking bright, but I soon hit a wall when I decided that I wanted to modify my blog.
I had a lot of difficulty getting Hugo to do what I thought it should be doing. For example, why couldn't I decide exactly where my art assets end up, why did Hugo need to make so many folders? I tried looking at their docs but I found them to be unhelpful. I eventually got the site up and running, but it was very draining.
My biggest take away from the experience was that Hugo is an opinionated tool that has its own ideas as to how a blog should look and how the content should be structured, and I did not feel like fighting with it.
I recently encountered these two articles and they inspired me to give this blog another shot. The articles convinced me that writing my own Static Site Generator would be fun project to try.
I decided to write the script in Go. I have been using Go a lot lately and it seemed like a natural fit for this project.
The first thing I needed to do was to find a library to parse Markdown files. At first I tried Markdown Parser and HTML Renderer for Go but I ran into a few problems. I wanted my blog to have syntax highlighting for code snippets, but this parser only added a class name to the
Another issue was that I wanted to use Front Matter for meta data and configuration, but I could not figure out how to do that with this Markdown parser.
I was able to get inline styled syntax highlighting and Front Matter by using the goldmark Markdown parser.
Go's standard library comes with its own templating engine. It's nice not having to use a dependency for this, but Go's templating is not easy to use. It is essentially a programming language in and of itself. Its syntax is confusing and it often does not do what I expect it to do. I lost a lot of time trying to figure it out.
I use templates to generate all the "infrastructure" aspects of the blog. This includes the front page, header and footer. Using templates allows me to propagate changes to all pages of the blog. For example, let's imagine that I had made each blog post manually and hardcoded the header into each article. If I wanted to add a new section to the header I would have to manually update all the blog posts. Using templates allows me to make the changes without having to make tedious and error prone edits.
I am also using templates along with Front Matter to accomplish the following:
- Show only published articles on the front page
- Show articles in chronological order on the front page
- Show an article's publication date in an article
Templates have the ability to print the output of arbitrary Go functions. I use this to show the current year in the copyright notice in the footer.
Whenever I start a web based project I think to myself:
"Don't waste too much time tweaking how it looks, just get it to work!"
This never, ever, works out this way. Playing around with CSS is an endless vortex that I always get sucked into. One thing I did this time around is that I made the CSS style myself and I tried to make it mobile friendly, which is something I failed to do in my last blog.
One CSS decision I made which is debatable was inlining the stylesheet within the template rather than loading it externally. Loading it externally is good because you can make changes to the style without having to regenerate the entire blog. However, inlining the stylesheet allows for the user to see content faster. I could have gone either way but I decided to optimize for the reader rather than myself. However, building the blog only takes a few milliseconds so this isn't really an issue, at least for now.
I knew from the start that I wanted to have special non-article pages on the blog. For example, the Projects and About sections. These are just blog posts written in Markdown, but I use the Front Matter to not show them on the front page and to not show a publication date.
Since the blog is just a few html and image files uploading them to my server is pretty easy. I wrote a little
bash script that uses
rsync to upload only the files I want. This means that to publish a new article all I need to do is:
$ ./blog $ ./upload.sh
As I mentioned earlier one of the things that annoyed me about Hugo is the file structure that it generated when you built your blog. I wanted mine to be a lot simpler. The file structure looks like this locally:
- Blog - blog (generator script) - upload.sh (uploaded script) - index.html (home page) - posts/ (articles) - post_name/ - post_name.md (blog post) - index.html (parsed markdown) - image.jpg
When I run
upload.sh it pushes the
index.html home page file along with the entire contents of the
posts/ folder (except the markdown files) to my server.
The file structure on the server it looks like this:
- index.html (home page) - posts/ (articles) - post_name/ - index.html (parsed markdown) - image.jpg
I saw a comment on Hacker News where some one said something along these lines:
If you build your own Static Site Generator, make sure you write a READ_ME file so that you won't forget how to use the tool you built.
I thought that was a great idea and I made sure to update a read me file each time I added any new features to my script, came across any limitations or had any ideas for features I wanted to add in the future.
This project was a lot of fun to work on. It felt great to hand craft a tool that was built to my exact specifications. I feel pretty confident that I will be able to add new features in the future without too much frustration. Now all that is left is to actually write some articles!