A quick look at how my site turns plain markdown into a fast, static website using Zola.
Published 23rd Nov, 2025
Like everyone out there, I started building websites with raw HTML and CSS, designing buttons, experimenting with retro themes, and trying just about anything that looked fun. Eventually, I discovered web frameworks that were incredibly fast, but honestly, I was never able to get my head around them. Not because they weren’t interesting, but because they felt a little too heavy for my brain.
My first website was plain HTML with a little bit of CSS. I wasn’t very familiar with any of the pre-built CSS libraries that existed back then. That was it, just a simple page with a hint of color (I really wish I had taken a backup at least). Then I came across Bootstrap CSS. It was sleek, easy to use, and with a single CSS file you could create an amazing looking site without writing a single line of custom CSS, not even for padding.
Time flew. Bootstrap laid the foundation for me to start writing my own CSS from scratch, experimenting with different layouts while referencing the maintainers code practices. But eventually, I got bored. I lost the spark. I was constantly looking for something new.
That’s when I came across Bulma, another sleek framework for web artisans. It was simple, elegant, and a great alternative to Bootstrap. I used Bulma everywhere, for every project, internal or external. It feels great to see how far that journey went.
I got so into using Bulma that I even crafted my own mini CSS framework called z3, a tiny collection of elements (forms, sliders, etc.) you could use on your site. It only supported light mode, I don’t maintain it anymore, but it still looks quite modern.
After rigorous experimentation, I finally settled on Tailwind CSS, the only CSS framework that now powers absolutely everything I’ve built or ported. This very website uses Tailwind. It’s modern, flexible, extensible… I could go on and on about it.
Once you have a solid CSS framework, writing HTML from scratch starts to feel a little odd and time-consuming. If only there were a way to write a simple text file and watch it magically turn into content, just like the old blogging days. That’s where SSG’s come into play. A static site generator automates the creation of static HTML pages, building a full website from raw templates.
Yup, you read that right. All you need is to define a few templates, apply some styling, start writing your actual content in Markdown, compile it, and you’ll have a production-ready static website waiting to go live.
And just like CSS frameworks, there are tons of SSGs out there, each designed for different purposes. I personally started off with HUGO, an open-source SSG, but for some reason it didn’t click with me. I then moved on to 11ty, which is based on Node.js, but I eventually got bored again. After hours of browsing around, I finally came across Zola, the SSG that now powers this entire website.
Oh, you’re in for a treat with this one. Everyone has their own personal preferences, and when it comes to SSGs, I’d still stick to Zola even five years down the line. Here are a few features I personally love:
A typical directory structure is incredibly clean. Your HTML templates go into the templates directory, and your Markdown files sit inside the content directory. That’s pretty much it.
-rw-rw-r-- 1 tin tin 825 Nov 22 21:05 config.toml
drwxrwxr-x 4 tin tin 4096 Nov 20 00:12 content
drwxrwxr-x 3 tin tin 4096 Nov 21 00:35 static
drwxrwxr-x 3 tin tin 4096 Nov 22 21:28 templatesI’ve customized my directory structure to include a production version of the config.toml file. This ensures that during container builds, Zola actually picks up the production configuration. It simply contains extra variables needed to define my CDN and static assets.
Based on my current workflow, the deployment is a partial DevOps style process with two major steps. Woodpecker (CI/CD) triggers the pipeline, which runs an Alpine container with the Zola binary available and builds the website.
A typical command on a Linux box would be:
zola -c config.prod.toml buildThis outputs the full website with the rendered content into the public directory. Woodpecker then picks up those generated files and replaces the existing ones on my homelab. That directory is mounted as a host volume inside the Nginx container that serves this website. As of now, the entire stack runs smoothly without needing any additional changes, and I’m really happy with how stable it is.
Oh, and a quick note: Woodpecker is a great CI/CD engine for beginners. It’s self-hosted, open-source, supports OAuth2, runs in a container, and comes with a simple yet sleek web interface for monitoring pipelines.
Yes, but only in cases where I’m not working on a fully-blown website, like a CMS. SSGs are best suited for small static content without any heavy lifting. They’re ideal for a blog, documentation site, or a portfolio. If you’re looking to get started with SSGs, I’d recommend checking out the Awesome Static Generators repo on GitHub. It lists a wide range of SSGs you can explore.
That’s it for this one, if you plan on building a website using an SSG, do let me know, I’d love to be a part of it!
You can write to me at [email protected]. Email services are insecure, consider encrypting emails with my PGP Key if you're sending me something sensitive.
Loading comments