How this blog is made
A brief overview of how this blog works under the hood.
TL;DR:
- Zola — static site generator
- Kroki — diagram rendering
- Bulma — CSS framework
- Cloudflare Pages — hosting
- Namecheap — domain name
- A few hacks — as always
- No JavaScript :)
🔗Prehistory / Why?
It all started when I was writing a travel blog (in Russian). After some time, it evolved from just a stream of photos to more deep and thoughtful content, which required some thought put in it as well as editing, planning, drafts and formatting. The natural way to keep these drafts was in Markdown, and generating a static website was in a stone’s throw from here.
Also, I was thinking about a place to dump my developer’s notes. All in all, I started looking into static site generators and decided to go with…
🔗Zola
Unlike Hugo , Zola is much younger, and thus its community is much smaller. There are no myriads of fancy pre-made themes that look awesome. But for me, this turned out to be a perfect match.
I started with Hugo, but quickly got overwhelmed by its complexity. I picked up a good-looking theme and tried to hack on it, but OMFG that was tough! Lots of JavaScript everywhere, weird templates, TONS of CSS… It was unbearable to change anything: things just kept falling apart. At this point, I realized that the only possibility to make things look the way I wanted them was to create a theme from scratch.
Looking around, I found Zola and decided to try it (yeah, because of Rust). And it was so much more sensible! I started hacking on one of the default themes but quickly rewrote it all from scratch.
The basic idea is simple:
You write your posts in Markdown (e.g. this page looks like this)
You have templates that explain Zola how to build a web page from it:
index.html
- the front page. I just symlinked it tosection.html
, since they are the samesection.html
- a template for a page with post listpage.html
- a template for a page with a post itself
The template language (Terra) is very similar to Jinja2, which should be familiar to all Ansible users
Templates can extend other pages, e.g. I use a
base.html
template that contains header and other common stuffSass is supported out-of-the-box!
To extend Markdown syntax, you can use shortcodes. Shortcode is also a template that can be inserted from Markdown, e.g.
templates/shortcodes/hint.html
:{{ text }}
will allow you to create tooltips like this :
How awesome is that? I use shortcodes to insert:
- Google Maps iframes
- Open Street Maps iframes
- YouTube iframes
- Images and videos with nice-looking comments
- Katex formulas
🔗Kroki
I like keeping diagrams in plain text format. It makes them easy to edit, read and share. It also improves collaboration, since you can now make readable Pull/Merge Requests.
A good tool for such task is PlantUML. It even provides an API to render images. However, you need to send your diagram in GET request, using special encoding, which Zola doesn’t support. POST requests are implemented, but not enabled on the public server.
Luckily, there is Kroki! It wraps a lot of tools under a unified API: you just send POST requests with your diagram data and get SVG or PNG back. We only need to write a shortcode:
{% set postdata = load_data(
url="https://kroki.io/plantuml/svg",
format="plain", method="POST",
content_type="text/plain",
body=body,
required=true
)
%}
{{ postdata | safe }} {% if comment %}
{{ comment | markdown | safe }}
{% endif %}
So now this section in Markdown
{% plantuml(comment="simple diagram") %}
participant Zola
participant Kroki
Zola -> Kroki: POST /plantuml/svg\nContent-type: text/plain\n<diagram_data>
activate Zola
Kroki -> Zola: SVG image
deactivate Zola
Zola -> Zola: embed SVG into HTML
{% end %}
… renders into this:
The rendering happens only once - during the site generation step. A diagram then exists as SVG image embedded right into HTML. A cool feature with such approach is that users can copy text from diagram labels, but a downside is that you can’t just download an image. However, you can extract SVG code from the DOM and put it into a file.
🔗Bulma
It’s hard to create a good-looking site with plain HTML nowadays. I use Bulma as my CSS framework, and I am mostly happy with it:
- No JavaScript required
- Modularity, meaning smaller asset size
- Sane configuration
Downsides:
- Has some rough edges, when you need to hack some styles with custom overrides. Not many, but still.
- Isn’t developed very actively. But maybe that’s an advantage in the modern world, who knows? :)
The whole Bulma repo is added as a git submodule to the blog. Then from sass/site.scss
I can import the required components, and Zola will compile them into a single CSS file.
The result is pretty awesome: I maintain only ~250 LOC SCSS stylesheet, most of which is a custom table of content implementation . This file is rendered into a ~200KB CSS file, which is a bit too much, but not drastically.
🔗GitLab
I use Gitlab as a hosting service for the code, because it’s the only non-GitHub option available in Cloudflare Pages. The CI setup is pretty straightforward:
- Install Zola
- Render the blog
- Copy it to the
/public
folder
The artifacts are not actually used, since Cloudflare Pages run their own pipelines on every push. But it’s nice to have a historical backups, I guess.
🔗Cloudflare Pages
CloudFlare is nice, because it’s EVERYWHERE, which means the best experience for the end user. It also supports Zola, though it’s not documented anymore for some reason 🙂
Also it gives some analytics, even though it’s very highlevel (for the best).
🔗Namecheap
As the name suggests, it’s a cheap domain registrar. That’s it.
I decided to go with d .net
domain, because I liked the idea of having a network of my own. There are just 2 services on it, but I plan to expand it in the future.
🔗Hacks
One last problem is that by the web standards, any website should have a www.
resource, but GitLab doesn’t provide it. The solution is to host a web server somewhere that will do just one thing: redirect www.your-blog.com
to your-blog.com
. Not having this resolution will make your site even less favorable by search engines, so it’s a good idea to have it.
Once you have a web server, you could add a www
A-record to a DNS service that will point to that web server. But where to find it?
Luckily, I was already running a server for my Telegram Bot (the post about it is coming soon!), so all I had to do is to change the Caddy’s configuration file a bit to add the redirect.
The server runs on Oracle Cloud, which gives you two VPSes for free. Take a look at my terraform scripts, which create these resources.
🔗JavaScript 🙅
You might have noticed that I try to avoid JavaScript as hard as I can. JS is a cool language with lots of great features, but using it on a simple static website seems like an overkill to me. I advocate for using it when it really makes sense: dynamic applications with intensive user interactions. My blog is definitely not in that category 🙂
Unfortunately, nowadays, JS sticks out of everywhere, even CSS frameworks tend to depend on it, which is bizarre in my opinion. You still need to have JS enabled to view the blog properly, since iframes use it a lot (e.g. Google Maps, YouTube), but it is not required for the basic functionality.
This also means that I have no trackers and I don’t know how popular this blog is, which posts are interesting and which need improvement. However, I consider this a good thing. I (imagine that I) write content mostly for myself and a few people that I’m familiar with. This takes a lot of pressure off, so I can relax and not think about views and being 100% accurate all the time.
🔗Conclusion
Overall, I’m pretty happy with the setup right now. The blog is lightweight enough to my taste, easy to maintain and hack on. It also costs absolutely nothing.
The editing process is enjoyable: markdown allows me to focus on writing and not spend too much time on technicalities. Once the post is pushed and draft
is set to false
in a preface, the job is done.
🔗Services used in the past (left for historical reasons)
🔗Freenom
Freenom is a (free) domain registrar, which serves .tk
, .ml
, .ga
, .cf
and .gq
zones. For free, you can get a domain only for a year, and then you are required not forget to renew it. The other downside is that there are plenty of scam sites in these zones, so search engines do not even try to index anything there.
You won’t find my blog on Google because of that :)
The other problem is that it is not quite stable: even the front page doesn’t respond sometimes. Also, one of my domains got deregistered for no reason, and I can’t get it back as it entered some weird state and disappeared from their system completely a few years ago 🤷
If you are willing to live with these handicaps, welcome!
Update: The ml
domain was taken back from FreeNom by the government of Mali. I should have been able to still renew it, but FreeNom didn’t allow me to do so for unknown reasons. Welp, I’m on .net
now.