I know a lot of people who have interesting things to say: when I can, I try to encourage them to write their own blogs. I think every developer who has interest should do it, with the minimal hurdle possible.
However, for reasons I cannot fathom, Medium has become the blogging platform of choice. Let’s face it, while the platform is okay-ish for non-technical posts, it’s not adapted for subjects that involve code - and formatting.
Besides that, Medium has a huge problem. If you use Medium, you basically surrender your own content to them.
Medium sucks for programming articles https://t.co/7tnF5Y7pjk Or on a more positive light, do create your own blog 👍— Nicolas Frankel 🇺🇦 (@nicolas_frankel) August 14, 2019
In this post, I’d like to describe my blogging stack and publishing process, in order for everybody interested either to start one’s own blogging journey or migrate one’s existing stack and keep control over one’s content.
As of now, the following stack suits me quite well. Yet, it might not be a great fit for every context. Hence, I’ve included a section listing some alternatives of some bits and pieces that might be more adapted.
The blogging platform is Jekyll, a static site generator: At its root, it reads Markdown files organized in a specific folder structure to generate HTML files that define the final blog content at build time. Compared to dynamic sites such as WordPress, it has the benefits of being fast - simple HTML, and secure - no PHP nor SQL injection.
But in some cases, e.g. simple boolean logic, or writing the publishing date, HTML files are not enough. To manage dynamic content, Jekyll integrates Liquid tags that allow simple logic.
Jekyll is built around a plugin architecture, to customize the platform. There are different types of plugin, depending on the kind of desired customization:
- Generator: generate additional content
- Converter: change a markup language into another format
- Command: add subcommands to the jekyll executable
- Tag: add additional Liquid tags
- Filter: add custom Liquid filters
- Hook: extend the build process
Plugins are written in Ruby. Plugins that need to be shared (or designed to be generic) can be installed as a Gem, while custom ones just need to be stored in a specific
_scripts folder. For example, a plugin generates the
sitemap.xml for the site.
To publish a new post, the process is the following:
- Create a new Markdown file in the dedicated
- Add it to the Version Control System, and push it
- This should trigger the build that should include:
- Generation of the HTML content
- Deployment of said content on a web server to make it accessible to the world
The main issue regarding static sites is how to let readers provide feedback - comments. To cope with that, there are "Comments-as-a-Service" providers. Jekyll integrates Disqus natively, a widespread CaaS.
From those foundations, I implemented the following customizations.
The Asciidoctor file format
I always found Markdown to be quite limited. When its limits are reached, one can always fallback to raw HTML, but then one tends to write a lot of HTML.
I found the Asciidoctor format a much better fit. Fortunately, there is a dedicated plugin to manage this format. With proper configuration, it becomes possible to write posts in Asciidoctor format.
UML is far less ubiquitous than most UML trainings claim. However, I still find it a quite useful way to communicate to stakeholders - or readers.
I found PlantUML some time ago: it allows to describe UML diagrams with simple text files in a custom syntax. There’s an online version available, as well as a Docker image. Regarding Jekyll, integration is provided by another plugin.
Jekyll is based on standard templates, with dedicated CSS classes. For that reason, Jekyll is able to provide themes based on those classes. Most themes are made available through Ruby gems. Changing a theme is just a matter of installing the gem and using it.
In my case, I re-designed the templates available in Jekyll. Hence, that made those theme gems useless… but I made my own style through a combination of custom and existing CSS.
For the record, Jekyll integrates with Sass out-of-the-box. This makes the process of creating one’s own stylesheets a bit less painful.
Version Control System
To start with Jekyll, one clones the GitHub repository, and customize it. To track changes, a VCS needs to be used. Because Jekyll is initially made available via Git, the logical follow-up is to continue to use it.
Jekyll is hosted on GitHub but I chose to use GitLab instead, because GitLab provides free unlimited private repositories. While my blog’s content is free for everyone to access, I prefer to keep the internal workings of the platform to myself.
I’m using Jekyll for blog posts, but also to publish my past and future talks. I also want talks to be indexed and parsed by Google in a structured way. For that, it’s possible to use the schema.org microformat. It wouldn’t be feasible to copy-paste the same tags for every talk.
To automate the generation process, I created a generator plugin that reads YAML data to in order to create the page. Even though I don’t know Ruby, it’s quite straightforward to create a plugin using the available documentation and existing examples. Developing a plugin is a great way to customize one’s Jekyll instance.
To remove every extra characters, a third-party plugin is available:
Jekyll HTML/XML/CSS/JS Minifier utilising yui-compressor, and htmlcompressor
It offers a lot of minification options, including the removal of line breaks, compression of JSON, etc.
jekyll command is used to generate the HTML content. As software developers, we should strive to automate as much as possible. Since my Jekyll source is hosted on GitLab, it’s only logical to use GitLab CI to build the site.
Thanks to GitLab, the build is integrated so that a commit to the
master branch automatically triggers it.
Once the site has been generated, it’s necessary to host the blog’s content. Fortunately, GitLab offers GitLab Pages, a static website hosting solution.
Again, thanks to GitLab, the build file can be configured with an additional publish step.
Here’s the configuration I use, to serve as a template:
variables: JEKYLL_ENV: production GIT_STRATEGY: fetch GIT_DEPTH: "3" before_script: - cd /builds/nfrankel/nfrankel.gitlab.io pages: stage: deploy script: bundle exec jekyll b -tV --config _config.yml,_config/_config_prod.yml -d public artifacts: expire_in: 1 day paths: - public only: - master
Miscellaneous customizations and improvements
- Custom domain
By default, the website is served as a subdomain of
http://<reponame>.gitlab.io. For "marketing" purposes, it’s better to use one’s own domain. GitLab Pages allows to serve the site under a domain you own e.g.
https://blog.frankel.ch/. Just check the relevant documentation.
As mentioned above, static sites are much faster than their dynamic counterparts. However, GitLab Pages' performance can be improved by using a CDN. As CDNs go, Cloudflare can cache a whole lot of content on edge servers located all around the globe. This allows to store the content closer to each user, and to improve the response time by an amount depending on the distance between a user and the GitLab servers. Icing on the cake, Cloudflare’s free tier offering includes that feature.
As I mentioned above, what I describe works for me perfectly. Yet, there might be alternatives to consider. Those are only suggestions I’m aware of, this is by no way an exhaustive list.
Based on Go
Based on Python
As mentioned above, my preference goes to Asciidoctor as Markdown is much too limited IMHO
I think GitHub has now a free option for private repos
If you’re already a user or are in love with Atlassian products
Makes a lot of sense if you already are using GitHub
Not battle-tested yet
Both seem to be equivalent based on my past experience
No free tier that I know of
If you want to start blogging, there’s no reason to use a platform that will get monetize your content, leaving you with nothing. Writing a blog post is a lot of work, the least you can expect in return is some sort of recognition from it. I hope this post will inspire you to start your own blog, or to migrate your existing one to a place where the content belongs to you.