2020-09-27-switching-to-own-ssg.md (9327B) - raw
1 <!-- title: Switching to my own static site generator --> 2 <!-- slug: switching-to-own-ssg --> 3 <!-- categories: FOSS, Personal domain, Projects --> 4 <!-- date: 2020-09-27T16:27:00Z --> 5 6 Since the start of this website (its first anniversary was a couple of weeks 7 ago!) until recently, I have been using the static site generator [Hugo][h]. 8 Static site generators are very useful when building relatively complex static 9 websites, and Hugo has served me well. I have also used [Lektor][l] and 10 [Jekyll][j] before for other projects, but for a site with a blog, I like Hugo 11 the most. However, with time, some issues have arisen with Hugo, and I finally 12 decided to change my site's generator. 13 14 ## Issues with Hugo 15 16 If you build your website with a static site generator, it will probably be the 17 most critical dependency of your site. Of course, it's a dependency I'm fine 18 with as it makes things much easier (dealing with Markdown content, categories, 19 web feeds...), but if something goes wrong, the site won't render as you want. 20 Hugo in particular is a very big project and I don't feel like jumping into the 21 source code every time I have an issue with the program (especially since I've 22 never used Go, and I don't want to spend hours for minor annoyances). Although 23 Hugo works wonderfully, I have encountered moments where it has acted 24 unpredictably, and documentation doesn't help most of the time. 25 26 On top of that, although it works perfectly well (and it is one of the most 27 popular SSGs), it is on a beta stage and the developers have made 28 backward-incompatible changes without warning in the past. The change I have in 29 mind was clearly stated on the release page, but I normally let my package 30 manager handle the updates, and I want my computer to keep working correctly (or 31 throw big red warnings all over the place). In this case, HTML inside Markdown 32 files stopped rendering, and I only found out coincidentally a couple of weeks 33 later as the web feed was not valid anymore. From that moment on, I started 34 checking the release notes for every update (which are frequent, about once a 35 week), but it was an annoying routine. 36 37 I understand that the program is in beta and it was on me to check for breaking 38 changes, but to be fair, Hugo is marketed as a fully functional program (as if 39 it wasn't on a beta stage) on the official website. Considering my last issue, 40 this was concerning and ended up creating uncertainty on the stability of Hugo 41 and the transparency of the developers, so I decided to change my site 42 generator. 43 44 ## Taking the leap 45 46 I wanted to move to something lightweight that could still be useful in a few 47 years' time, ideally a program that was easy to understand and maintain. The 48 problem was that I had some very specific needs that small programs didn't 49 fulfill, leaving only big programs as an option (which I didn't want to use). I 50 thought of the possibility of creating my own site generator, but it looked like 51 a large task I didn't want to spend my time on. Hugo was working fine, and 52 although I kept looking up other SSGs when I discovered them, I stopped actively 53 looking for alternatives or thinking about designing my own. 54 55 Until the night of the 5th of September, when I came across [makesite.py][ms]. 56 This project was just perfect, and I couldn't resist. Let me show you an extract 57 of the README: 58 59 > Have you used a popular static site generator like Jekyll to generate your 60 > blog? 61 62 Yes... 63 64 > I have too. It is simple and great. But then did you yearn to use something 65 > even simpler to generate your blog? Do you like Python? Perhaps the thought of 66 > writing your own static site generator crossed your mind but you thought it 67 > would be too much work? 68 69 Yes, yes, and definitely yes! 70 71 > If you answered "yes" to these questions, then this project is for you. 72 73 Nice! That night I read the README and the source code (which is shorter than 74 the README). The program is very simple and a lot of the basic functionality I 75 needed out of a static site generator was already there. On top of that, it 76 didn't use any non-standard Python library except for the Markdown parser. I 77 really liked the project and I thought it could be the foundation of my personal 78 static site generator. 79 80 It was. The next morning, I started coding to make it usable for my website. I 81 had to implement many new features, but with Python it was [easy and fun][xkcd]. 82 After two days of working on it, I finally released my site using a personal 83 fork of makesite.py, [gensite.py][gs]! 84 85 ## The new benefits 86 87 So, why change the SSG if Hugo was working fine? As I said, I've had my issues 88 with Hugo, and I don't want to be forced to leave my static site generator if 89 more arise in the future. I don't know if I'll be able to switch SSGs when (and 90 if) the time comes, and now I have the time and motivation needed to do it, so I 91 decided to take the chance while it was there. On top of that, *gensite.py* is 92 not only my "way out of Hugo", it is a program that has many features that could 93 have made me do the change without having any troubles with the last SSG. 94 95 First of all, the program is very small, it's only about 270 lines of code and 96 it's written in Python. That makes it very easy for me to read and understand 97 the whole program very quickly, even if I have completely forgotten everything 98 about it. Obviously, this doesn't count the lines of code of the libraries it 99 depends on, but those are all standard libraries and the functions are easy to 100 understand, except for the Markdown parser, but if that ever gives me any 101 trouble I can change it without much effort. 102 103 Since *gensite.py* is made exclusively for my website, it is more closely tied 104 to the rest of my site. For example, it doesn't have a complex template engine, 105 instead, templates only process the following two snippets: 106 107 - `{{ var }}`: substitutes the string for the value of variable `var`. 108 - `{{ _if var }}text{{ _fi }}`: will render the text `text` if variable `var` is 109 defined. You can't have an `_if` inside another. 110 111 If I need anything more complex, I will use Python to create the text and pass 112 it as a variable when rendering the template. I prefer this approach as it is a 113 lot nicer to implement those features in Python than it is with a template 114 engine. For some pages—for example, the archive—Python does some more heavy 115 lifting and creates part of the HTML. This can sound weird in comparison with 116 other static site generators, where HTML is only dealt with in the template 117 files, but it makes things simpler, and I no longer need hacky templates to 118 create certain outputs. 119 120 Moreover, I like the file structure a lot better (I designed it!), and if I ever 121 want to change it, it shouldn't take long to do so. Similarly, any other design 122 options are exactly as I want them to be, since it is me who decided them. In 123 case it is not clear: everything works exactly as I want it to! 124 125 Finally, it's a project that doesn't move too fast. One of the problems with 126 websites is that links are easily broken: entities change their backend, run out 127 of money, mess up an update, etc. and let their links break. Right now, I am 128 pretty dedicated to my website, and if my SSG broke something on my website, I 129 would spend the time to fix it, but I can't ensure I'll do the same in two or 130 five years (and I don't want to break any links, even on the long term, but 131 that's a post for another day). Unless something happens with Python, 132 *gensite.py* will work and so will the generation of my website. There won't be 133 any updates that break some random page or that change a certain behaviour[^u]. 134 I hope *gensite.py* can stand the test of time, but we'll see... 135 136 [^u]: Also, whenever I make changes to *gensite.py*, I can run `diff -r` to 137 check for differences for the outputs before and after the update. With Hugo, 138 many files changed without explanation (although it was mostly style choices, 139 it made it hard to see the real changes in content between updates). 140 141 ## Final comments 142 143 Forking *makesite.py* and setting up everything I needed for my website was very 144 fun, but it is surely a process that not everyone will enjoy. I have lately been 145 leaning towards software that is a simple as possible, software that is easy to 146 understand and change if needed. It takes time to set up, but once it's working, 147 you can forget about it (and if you need to make changes, they are quickly 148 implemented) and you will have software that works exactly as you want it to. I 149 am very meticulous about this website and try to have good control over 150 everything that happens during the website's generation, and I couldn't be 151 happier with *gensite.py*. 152 153 On another note, I don't want to end this post without saying that Hugo has been 154 a great static site generator, and I'd recommend it to anyone who wants to have 155 a blog on a static website. In a new update with breaking changes, they did 156 throw errors if the old feature was used, so maybe my experience wouldn't happen 157 again. Just remember, it's still in beta. 158 159 160 [h]: <https://gohugo.io> "Hugo" 161 [l]: <https://www.getlektor.com> "Lektor" 162 [j]: <https://jekyllrb.com> "Jekyll" 163 [ms]: <https://github.com/sunainapai/makesite> "makesite.py — GitHub" 164 [xkcd]: <https://xkcd.com/353/> "Python — xkcd" 165 [gs]: <https://git.oscarbenedito.com/oscarbenedito.com/file/gensite.py.html> "gensite.py — git.oscarbenedito.com"