For probably the past three or four years, my icon gallery sites (iosicongallery, macosicongallery, and watchosicongallery) have been powered by Jekyll. Each icon on the site is a “post” in Jekyll without any body content, i.e.
--- title: "Facebook" slug: facebook date: 2018-04-24 # more stuff here ---
Each site had its own Github repo consisting of the posts and images for each site’s content. In addition, each repo contained a git submodule which constituted the theme for each site (i.e. shared code, templates, styles, images, etc.) The site was served by Github pages, so anytime I made an update to one of the sites’ repos, Github would handle building and deploying my site.
This has all worked pretty well over the past few years, but a few drawbacks of this approach have increasingly reared their head:
- Speed: Jekyll was slowing down. iosicongallery.com has over 1,000 “posts” and building or developing the site locally was getting slower and slower. I found myself waiting almost a full minute for the site to generate.
- Github pages: I have to play by Github’s rules for deploying a site via Github pages, including the fact that the site has to be generated by Jekyll which is what I was trying to switch off. Plus Github pages doesn’t give you a lot of the bells and whistles you get with other solutions (like
https, deploy previews, static site generator of choice, etc). So my hosting solution was coming into question as well.
I’d been thinking about switching over to Netlify as my host for some time, which would free me from the tyranny of only a single choice when it comes to a static site generator. So I decided to finally take the plunge and get a new static site generator and hosting solution for my icon galleries.
Choosing a Static Site Generator
As you’re probably aware, your options for a static site generator these days are basically like your options at a buffet: unlimited. I had my finger on the pulse of what was happening with modern static site generators, but I checked out StaticGen to refresh my memory. At the time of this writing, the top five static site generators on that site were:
- Very modern, an “up and coming” framework, i.e. popular with the cool kids
- Templating with React components
- Primary focus is towards server-rendered applications, not as a static site generator, though you can do both.
After digging through their docs and trying some of their example code around generating a static site with my own content, I eventually gave up because I couldn’t even get the thing to work. Maybe that’s because I’m just not that good with computers and tooling, but I’m going to chalk it up to the fact that using this tool as a static site generator is not the intended, primary usage. It’s like a “hey you can do that too!” but the primary use cases and documentation focus on it being a framework for server-rendered applications. In fact, if you Google “nextjs static site generator” the first result drives you to a project called nextein which claims to be “a static site generator based in Next.js”.
- Very modern and popular (latest reactjs.org was built on top of it). At the time of this writing, you’re not cool unless your doing static site generation on top of Gatsby
- Templating with React components
- Modern JS technologies (babel, webpack, graphQL, etc)
- Modern JS technologies (babel, webpack, graphQL, etc)
- Perhaps too much complexity for my simple use case
- The project/people behind it just got funding so Gatsby is turning into a company (unsure if this is a con, but may become one someday?)
I really wanted to use Gatsby. I wanted to write my templates in JSX. And Gatsby has some much attention these days, I knew finding answers to questions would be relatively simple. The project has lots of activity and a strong developer base around it. All things I wanted from my new static site generator.
However, the one thing that really ended up being a deal-breaker for me was that Gatsby felt too sophisticated for my use case. One of the tests I had in my mind while evaluating these tools was that I would browse the documentation and if I couldn’t understand how to get started and feel excited about starting within five to ten minutes of reading the documentation, I gave up. I gave Gatsby even more time than that because lots of people were vouching for it. But at the end of the day, it felt like too much complexity for what I was trying to do. Too many variable web technologies that I was afraid could change in six months and I’d be playing catch-up constantly. I wanted something like what Jekyll had been: write my site and leave the code for years with minimal involvement. I didn’t feel like that would be possible with Gatsby (granted there’s probably a contradiction in there, that I wanted React but also code I wouldn’t have to touch and maybe you’re right, but having React vs. having React and Webpack and GraphQl and CSS-in-JSS tools and others felt like a bit much.) In the end, I could never muster up the courage to even try standing up a prototype. For me, there was just too much going on. I wanted something more like “here’s my markdown files, here’s my templates, go!”
- Insanely fast
- Matches the mental model I had for a static site generator for me
- Has documentation for transitioning from Jekyll
- Big developer base in China, so lots of good documentation, issues, and other collaborative information is not in English.
I really liked Hexo. After about three minutes of reading the docs, I had a clear picture of how to get started. I even got my site up and running in a crude fashion using Hexo’s framework and it was insanely fast. Jekyll was building my site in roughly 60 seconds while Hexo could do it in about 10. Plus the development build was incremental and also way faster than Jekyll’s.
For a while I thought I might even end up with Hexo. But the more and more I refined my prototype towards a production-ready product, the more and more I found myself struggling to find answers to questions. Anytime I Google’d an error or question, I’d find some comparable stack trace in a foreign language. In some ways, it almost felt like a bait and switch: Hexo’s docs were great at the introduction, but the more you got into actual implementation, the more you found how incomplete the docs were (or unclear, as though they were written by someone whose first language wasn’t English). So essentially I found myself having the same problem I outlined above with Jekyll, except instead of the code being in a foreign programming language, the ecosystem around the code was primarily in a foreign human language. I continued to build my site on top of it, but the further I got, the more I felt like this wasn’t going to work.
Fortunately, Hexo and I were still dating and we hadn’t gotten married, so I started looking around for other options.
- Extremely pluggable
- Simple concept and idea behind the code
- Little activity on the core project (in fact it appears segment, who built Metalsmith, recently used Gatsby for their static site)
- Community plugins are hit and miss in terms of activity/support
I had actually been introduced to Metalsmith on a prior project a few years back by my friend damassi, but my JS skills back then weren’t polished enough to really understand it. When I dug through Metalsmith’s docs, what really struck me about the framework wasn’t so much what technologies they were using under the hood (or rather which ones they weren’t using, no React, no Webpack, no Babel, etc) but the ideas behind the code. Metalsmith is built on the idea that (their take on) a static site generator operates on this simple premise:
- Take a directory of files
- Manipulate those files in a variety of ways
- Write the manipulated information to disk as a website.
Metalsmith touts itself as a “pluggable static site generator”. The core library is merely an abstraction for manipulating a directory of files. Everything else is done by plugins. The idea behind what Metalsmith was doing really attracted me, as code and technologies change but ideas persist. However, when trying to implement my site on top of Metalsmith I kept running into problems. In fact, I ran into problems enough times that I gave up. It wasn’t as convenient as Hexo which prescribed I do things a certain way. Metalsmith was more open-ended and (at first) I didn’t like that.
So I ended up doing a dance between Metalsmith and Hexo. When I didn’t like Metalsmith, I’d say “Ok I’m building this in Hexo”. Then when I got to the point that I didn’t like Hexo, I’d say “Ok, nevermind, I’m going to build this in Metalsmith”. Eventually I got so unsatisfied with both that I just told myself that I would build my own static site generator.
However, I eventually found this blog post which is what gave me the “ah-ha!” moment I needed to understand how Metalsmith worked. In the back of my mind, a line from Metalsmith’s docs kept coming into my mind which basically said “once you get how Metalsmith is working under the hood and what’s happening, it all clicks.” I finally had that moment and when it clicked, I realized Metalsmith was going to be my choice.
Don’t get me wrong, metalsmith has its drawbacks. But at the end of the day, the ideas behind the code rather than the particular technologies behind the code were what won me over.
Here’s an example of what I’m talking about.
So for my site I had a directory of
.md files which represented each icon as a “post”. I had a separate directory of images which served as the source for the actual icon image files. In Jekyll, that was just a static directory that got copied over because I couldn’t hook into the build process. So my permalinks to a post might be
/icons/:id/ where my
index.html file was served, but the actual source for the icon
<img> would be in whatever directory I had them in in my repo, so in the production site they’d be referenced at something like
/img/src/:id since Jekyll was just doing a straight copy of files and folders.
What was really cool about Metalsmith is that it allowed me to hook into node in the build process and do whatever I wanted. So when Metalsmith was building each post, it would look for my source icon images and copy them over to the build directory in the same place where it was putting the
index.html file for the icon’s post. This allowed me to build each site in a way such that I could leverage my site’s URLs as an interface for getting icons, i.e.
/icons/:id/ for the HTML representation of the icon and
/icons/:id/:size.png for the actual icon (i.e.
/icons/facebook/512.png would give me facebook’s 512px app icon).
I ended up going with Metalsmith for static site generation and Netlify for hosting and I’ve been happy for the few weeks I’ve had things this way. Granted, I could totally regret this decision in a few
years months weeks, but I’m happy now. And when it comes to personal projects, that’s all that really matters.