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 developers 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 (@Home for a long time I believe) (@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 foundation 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 _posts folder 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 .

My specifics 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. PlantUML diagrams 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. Theming 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. Content generation 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. Minification Jekyll can easily be configured to provide minification : the generated HTML content can minified, including the JavaScript content if any. However, there’s a caveat to that: line breaks are kept, and yet, they make up a big part of the symbols that could be safely removed. The out-of-the-box minification feature goes only as far. To remove every extra characters, a third-party plugin is available: Jekyll HTML/XML/CSS/JS Minifier utilising yui-compressor, and htmlcompressor — Jekyll minifier

https://github.com/digitalsparky/jekyll-minifier It offers a lot of minification options, including the removal of line breaks, compression of JSON, etc. Building The 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. Hosting 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 gitlab.io i.e. 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. Cache 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.

Possible alternatives 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. Tech Alternatives Comment Jekyll Hugo Based on Go Flask Based on Python Asciidoctor Markdown As mentioned above, my preference goes to Asciidoctor as Markdown is much too limited IMHO Git What else? GitLab GitHub I think GitHub has now a free option for private repos BitBucket If you’re already a user or are in love with Atlassian products GitLab CI Travis CI Makes a lot of sense if you already are using GitHub GitHub actions Not battle-tested yet GitLab Pages GitHub Pages Both seem to be equivalent based on my past experience Cloudflare Akamai No free tier that I know of