La Technique

Building a dev blog with the Pelican static site generator

I’ve long thought about starting a dev blog, and recently I’ve finally been able to prioritize setting one up. Here’s how I went through the process of launching this blog.

Rationale: why start a dev blog?

But first, why did I want to start a dev blog?

Well, for one, I’ve always thought that writing (at some length, and especially long-form) is one of the most important and valuable activities that any human can do. It’s difficult, but there are not a lot of things as rewarding as transforming thoughts into tangible words. It’s one of the purest forms of creativity, and a most satisfying one at that.

As someone who grew up in the era of Web 2.0, blogging has always been a natural venue for writing for me. I’ve maintained a blog, Reverse Delay, for many years now, writing there for leisure, but when I fully shifted into a software development and engineering career a few years back, I started getting an urge to write about my work. I would spend countless hours investigating issues, analyzing problems and designing solutions in the course of doing my job, and there grew this pressure inside me to share about these experiences, for anyone who might care to read and perhaps even find something of benefit. It was the same kind of feeling I had whenever I watched particularly artistic and thought-provoking films that led me to write a lot about cinema at Reverse Delay.

The thing is, with that kind of focus on cinema and culture-at-large established on my existing blog, it felt inappropriate for me to suddenly start posting about Python code or systemd administration or whatever such technicalities there. My regular readers, few as they already were, would just be utterly confused. I needed a new venue. Hence, I needed to start a dev blog. (A dev blog is also known as a tech blog, but “tech blog” has this connotation of a publication posting frequently about the latest shiny gadgets, which I don’t see myself doing.)

It would be somewhat dishonest not to mention—to admit—the aspect of a dev blog as a venue for selling myself: as a showcase for my skills as a tech person, an elaborate résumé. I realized this much when I created a Stack Overflow account two years back and briefly enjoyed answering some questions there. A few Q&As had me diving really deep into open-source code and documentation and old message boards and I thought, hey, this is some work that would be nice to show off should the need arise. It gave me additional reason to put together a place where I can collect the finer samples of my work, and a little bit of self-advertising isn’t bad. It’s even essential, in fact, if I am to make a good living.

Architecture and infrastructure: where to host?

With the need to start a dev blog already over-justified, the question of where to put the blog came up next. It was a question of infrastructure, of architecture in fact. If this blog was going to be a showcase of my work, I might as well put in the same amount of overthinking into setting it up.

I wanted several things for the blog, but some of these turned out to be conflicting requirements. I wanted to minimize the costs of publishing and maintaining it to be sustainable, but I also wanted it to be fast and reliable and I didn’t want the pages to be littered with unsightly ads if possible. I wanted readers to be able to leave comments, but I didn’t want spam. I wanted control over how the pages looked, but I also didn’t want to put too much effort into tinkering with CSS, which risked ending up with pages that are unusable or at least awkward-looking on certain devices.

One of my first ideas was to self-host a WordPress site on an AWS EC2 VM or Digital Ocean Droplet. This was just a knee-jerk urge that I abandoned quickly: I’m just too familiar with WordPress (I learned how to self-host it more than a decade ago), and I somewhat enjoy setting up servers (it’s like, hey, new toy!), but this clearly violated the need to be low-maintenance. A virtual machine gives me full control, but there is a tradeoff between control and effort, and I just might end up spending more time tinkering with my server configuration than actually writing my dev blog.

I considered several managed blogging services. Reverse Delay is powered by, which I chose for many of the same reasons of sustainability, etc., though the service is getting more and more ads over the years. Also, WordPress, while a great blogging platform, isn’t particularly suited for dev blogs. For example, while it now supports Markdown and code blocks, you can’t get syntax highlighting without additional plugins (a problem for the managed service more than self-hosted instances). is perhaps the most popular platform for tech people, though I’ve always been wary of it as a service (I haven’t actually tried it so my reasons are mostly subjective, often petty, such as my dislike for the default typefaces and the idea of ‘claps’). is fairly expensive.

I was very attracted to Hashnode because it’s focused on dev blogs, but I felt uneasy about it being backed by a very young company still looking for a business model, which raised questions about stability and longevity. I almost chose DEV Community because it’s like Hashnode, only a lot more transparent and community-driven, but ultimately I decided on something I’d have even more control over, and because I think I don’t yet need the network or community discoverability that platforms like DEV offered.

I ended up building a blog using a static site generator, to be hosted by Cloudflare Pages. Deploying static files on a CDN meant I would have virtually zero issues with performance and reliability. The last issue I had to resolve was the question of comments: this is still possible with static site hosting using services like Disqus, with just a bit of additional complexity and accounts wrangling, but after browsing the blogs of more accomplished devs than myself (such as Jeff Forcier’s, I decided that I didn’t need comments after all. My concern with comments was that if I’m going to put up, say, code snippets, and there turned out to be something terribly wrong with it but then people start using it, there won’t be an obvious way for them to know immediately. But I’m just overthinking again, and indeed there’s probably much bad programming advice on the internet even on blogs with feedback systems but without anyone actually sounding off warnings in the comments section. In any case, decent developers should (ideally) personally vet any programming help they get from the public internet. So I’m doing away with comments sections entirely, turning my dev blog into a one-way communication affair. Should anyone need to violently react to what I publish on it, I’m still reachable elsewhere on the internet.

I discovered Cloudflare Pages at the last moment; I was already starting to use GitHub Pages, when I thought about the awkwardness of a GitHub Pages site needing to be published from a public repository (meaning the content would be viewable from two sources, both in ‘compiled’ HTML and in Markdown or whatever source form it assumes in the source repository) if you don’t have a paid account yet—and there is no other reason for me to upgrade to such a plan on GitHub yet. Cloudflare Pages is just like GitHub Pages, only even more generous and less restricted: it has no bandwidth limits at all (versus GitHub Pages’ “soft” bandwidth limits), and supports a wide range of static site generators (versus GitHub which only supports Jekyll directly). I’m still using GitHub though to host the blog’s source in a private repository, only connected to Cloudflare for the automated publishing pipeline.

It’s quite interesting how far you can go on the internet these days using just generous free services like Cloudflare Pages (provided you have the necessarily knowledge and skills). You can run a website that’s simple, efficient, reliable, and internet-scalable yet zero-cost and ad-free. We’ve gone a long way from the days of Blogger and friends in the 2000s. With this setup I’m ticking off most of my requirements; it’s not necessarily a globally optimal decision, I didn’t employ some giant decision matrix with obsessively detailed evaluation criteria, but it’s a satisficing-enough decision. It’s one I’m happy with: it’s like going back to the simple days of Web 1.0, only with a contemporary twist.

That twist comes in the form of the need to learn new tools, because all decisions between trade-offs come with compromises, and the particular compromise I have to make is that I have to learn how to use static site generators first.

Pelican, the generator of choice

Fortunately, static site generators are actually quite fun, at least from my perspective as a web software developer. Having built applications with SQL databases and task queues and message brokers, using static site generators feels cute and quaint in comparison. These are neat tools that you feed with something like Markdown texts and from which pops out nice and nimble bundles of web pages. They are also very satisfying to use in a distinctly geeky way: instead of publishing a post by clicking a button as I’d do on, say, WordPress, with a static site generator set up on Cloudflare Pages I’d publish by entering git push on the terminal.

The selection process for which specific site generator I’m going to use was, this time, fairly simple. I first learned Jekyll (because of the aborted plan to use GitHub Pages), and it was nice, but with the move to Cloudflare Pages I could now switch to a generator from the language ecosystem I’m most comfortable with: Python. Perhaps all generators are usable even without a working knowledge of their underlying language—I was able to run Jekyll despite almost no knowledge of Ruby—but eventually this familiarity will come in handy, such as when you start having specific needs that need some tinkering with plugins. This also ties in with my need for my dev blog’s stack to be as low-friction and low-maintenance (for me) as reasonable. The exploration of other ecosystems can be done on another day.

I chose Pelican as the most popular (as measured by GitHub stars) Python-based static site generator that caters to blogs. (The most-starred Python generator is MkDocs, which specializes on documentation sites.) Pelican uses Jinja for templating, and I’m comfortable with that because it is similar to Django’s templating language.

Compared to Jekyll, Pelican feels quite a bit more clunky. For example, the settings needed to implement “pretty” URLs feel complicated: in Jekyll, this can be accomplished with one configuration line for both posts (articles) and page-type content, but in Pelican, you have to write separate *_URL and *_SAVE_AS settings for each content type (e.g., articles, pages, category archives, author archives, and so on). The separation of the *_URL settings from the *_SAVE_AS settings (the latter of which determines where the output files are saved relative to the directory tree) can be confusing at first, because while both are presented as if they relate to URLs only, the latter setting type is also a toggle that turns on and off the generation of specific types of pages. (It has effects on plugins, for example the one for generating sitemaps; it’s an interaction that I had to discover for myself.) At least the project’s docs are still largely helpful and already provide examples to copy for common use cases. I also expect that this complexity makes the generator more powerful in some way, I just haven’t thought of any use cases yet. Another Pelican quirk is the need for a plugin just to generate links to chronologically-adjacent articles (posts), which feels like something that should come standard in any site generator that is known to be used for blogs.

It all works in the end though, and after conquering this learning curve, I feel like I’m now set to use Pelican for a long time to come with minimal fuss. Using a static site generator means there is always some software maintenance involved, to keep the packages and dependencies up to date, unlike, say, when using WordPress where you can just log-in when you want to post and expect the changes to be introduced gently to you. But I expect any maintenance to be minimal and manageable. The Pelican maintainers seem to have a focus on backwards-compatibility anyway (which perhaps helps explain the oddities: they’re relics of the project’s age). Security is not an issue with static HTML sites as well, so updating dependencies can be done on a more relaxed pace (i.e., can be procrastinated upon).

Building a theme

With the questions of host and generator settled, I just needed to pick a theme to get going. Unfortunately, it turns out I can be very particular with a theme, and I found none that really suited what I wanted. Perhaps I just didn’t search widely enough (the Pelican themes listing isn’t currently very helpful), but now that I’m intoxicated with the power afforded by static site generators, I decided to go ahead, take advantage of the measure of control that Pelican afforded me, and I built my own theme from scratch.

This took way more time and effort than deciding on a host and generator. It also went against my initial requirement of hassle-free theming, but it also was a perfect opportunity for me to brush up on my HTML and CSS, which I first learned in the dark days of Internet Explorer 6. Of course I tried to keep up with the developments in this space, but with my professional projects I often just used frameworks (especially Bootstrap), and did only basic markup and minor styling tweaks. I learned a lot of small things while building my custom theme, but some of the most interesting (but not necessarily important ones) include:

  • The subtle differences between HTML sectioning elements, especially <article> and <section>, about which there is an excellent Smashing Magazine article: <article> vs. <section>: How To Choose The Right One”.
  • Practicing the use of CSS flexbox and grid: layout capabilities have improved leaps and bounds since the CSS 2 days, but for me it still sometimes involves some frustratingly invoking some arcane styling property, like a wizard summoning a dark arts spell, to fix some unexpected interaction between CSS’s myriad concepts. I had to review overflow in relation to nesting, and learn how margin collapsing contexts relate to grid layouts.
  • The dynamic viewport units, which I couldn’t yet use because it’s still new to browsers and hence not yet widely supported.
  • CSS transitions (a.k.a. animations) can produce very weird and jarring effects during page load, and the only solution I found so far is to (reluctantly) add JavaScript to delay the application of transitions until after loading is complete. I otherwise wouldn’t have any JS on my page (that is not injected by the harmless, privacy-respecting Cloudflare analytics service). I learned the solution from CSS-Tricks, which, by the way, is such an appropriate name for a website that is basically an authoritative source for the kind of arcane CSS invocations I complained about.

For SEO, I skipped using a Pelican plugin dedicated for such and decided to use only a sitemap, and to implement basic <meta> tags right in the theme (including Open Graph, so that my pages will look nice should people share them on social media and messaging apps). I believe in the fundamental principle of SEO, often buried underneath a mountain of dubious SEO advice on the internet, about focusing on creating unique, quality content rather than obsessing on the ‘marketing’.

Device compatibility is now no longer as much of an issue as when I first learned CSS thanks to web standards, and I’m quite confident my theme looks fine, or at least is usable, on the vast majority of devices out there, but sometimes I feel paranoid. This is the final challenge, the need to extensively field-test a website, but this is just something I can work on and iterate in the future.

Publishing the site

After all the overthinking and tinkering, my dev blog setup is finally ready. I whipped up an about page and a brief article about philosophy as the introductory post (to help make me look smart), and then I pushed the project to GitHub. I set up the Cloudflare Pages site (such a delightfully breezy process), and voilà, I have a shiny new dev blog on the world wide web. It’s like I’m back in elementary school and I have a fresh and pretty notebook I’d love to show off to my classmates.

With this, I’m excited to journey further into my software development career and tell you all about it.