My Blogging Flow - Part 1 - Under the hood
Tags: blog, hugo, gandi, digitalocean
Published: 2019-02-14 20:13:45

---
title: My Blogging Flow - Part 1 - Under the hood
published: true
tags: [blog, hugo, gandi, digitalocean]
canonical_url: https://dmerej.info/blog/post/my-blogging-flow-part-1-under-the-hood/
series: my-blogging-flow
---

*Originally published on [dmerej.info](https://dmerej.info/blog/post/my-blogging-flow-part-1-under-the-hood/). Keep that in mind when if you continue reading on this post on dev.to :)*

Several people have asked me how my blog works and how it gets written, so here’s a blog post about how I blog (so meta).

Let’s start at the beginning.

# The history of dmerej.info/blog

## Buying a DNS domain

The first step was to buy a domain name. I chose [gandi.net](https://www.gandi.net/en) because I only heard good things about their registration service. I like the “retro” feel of the `.info` <abbr title="Top Level Domain">TLD</abbr>, and the `dmerej` prefix is the one I use to shorten my name. Wether it’s a good thing or not, it’s too late to change it now, so there.

## Getting my own machine

I always wanted to control all aspects regarding the hosting of my blog, so I started by looking for a dedicated machine.

If you’re not familiar with the concept, having a dedicated machine means that you pay for the hardware and ssh access to a server owned by soneone else. In exchange, you get to install and configure everything by hand. If it sounds like a loosy deal to you, remember that [I value control over convenience](https://dmerej.info/blog/post/a-definition-of-the-linux-desktop/) :)

Anyway, I bought a server at a company called dedibox. (For the sake of completeness, I must say I’m now hosted by the nice people at [Digital Ocean](https://www.digitalocean.com)).

But enough speaking about hosting services, let’s talk about blog engines!

## Static or dynamic

There are two types of blog engines: _static_ and _dynamic_. It has to do with what happens when a visitor requests the article’s URL.

In a dynamic blog engine, the contents of each article is typically stored in a database, and the HTML is generated by the engine for each visitor. This means the server has to run some code for each visit.

On the other hand, a “static” engine typically generates a bunch of HTML files from sources written in a markup language (often Markdown) _beforehand_. Then all the server has to do is to present the correct file when a visitor wants to view a page.

Both of them have pros and cons:

- Dynamic blog engines can handle comments, compute statistics (like view count), and so on. But because they require a database and some programming language support, they can get hard to deploy. Finding a way to do backups properly can get tricky, too.

- Static blogs cannot handle comments or anything like that, but they are _very easy_ to deploy: you can simply use existing web servers (like `nginx` or `apache`) directly. Also, backup is easy - you just need to backup the source files, and a `git` repository is more than enough.

## Finding a blog engine

I must say I spent way too much time finding the engine I would use for my blog.

My guts told me I wanted a static engine, so I started fiddling with many static blog generators. Alas, they are _tons_ of static engines out there, and I almost gave up on finding the one I would use - there were simply too much choice.

That’s when I realized I was not tackling the problem correctly: I was worried on _how to publish contents_, but said content was _yet to be written!_

So I took a look at dynamic blog engines (less choice there), found Dotclear almost by chance, and started to write.

Finally, my articles were online and publicly readable by anyone on the world. What a joy!

Advice to my dear readers: if you want to publish something online, don’t make my mistake: make sure you have _some_ contents before worrying about its publication.

## The Dotclear period

Configuring `php` for Dotclear was a bit tedious, but once it was done I must admit it was quite pleasant to use. The admin view is rich and featureful, and the editing form is ergonomic. Comments are supported out of the box, and they are easy to moderate.

But I still I had a problem: I was receiving many notifications about comments but _almost all of them were spam_ :/

This was depressing, so I shot down the comment service and started looking for an alternative.

## The Hugo period

I went back looking for static engines, and found Hugo on [the StaticGen engine comparison website](https://www.staticgen.com/).

I immediately liked it:

- There are many beautiful themes available. (Dotclear themes are nice too, but they look a tad outmoded to me).
- Hugo is easy to install (just one binary)
- Its documentation is complete and easy to follow
- I no longer had to setup `php` on my server. Just a few lines of `nginx` configuration was enough.
- Plus it is ridiculously _fast_. More than one hundred pages in less than one second.

To work, Hugo need a _theme_. A Hugo theme is made of various _templates_, which control how the HTML gets produced, and some _static files_ (like CSS or images) that needs to be copied along the generated files.

Hugo does not come with a default theme, so after a few tries, I settled on [blackburn](https://themes.gohugo.io/blackburn/).

### Writing my own shortcode

The nice thing about Hugo is that you can customize the look and feel of your blog as much as you like. I still remember fondly the day I managed to implement the “movie script look” for the short scenes I wrote in [Heard and Seen at FOSDEM 2017](https://dmerej.info/blog/post/heard-and-seen-at-fosdem-2017/#scenes).

Here’s how it works.

First, I have custom `scene` shortcode inside the `layouts/shortcode` directory of the theme:

```html
<div class="scene">
<h1>
  {{ .Get "title" }}
</h1>
<p>
{{ .Inner | markdownify }}
</p>
</div>
```

This allows me to write things like this in the Markdown source:

```markdown
{{< scene title="Resurrecting Dinosaurs" >}}
SPEAKER: I did *not* expect to have a win32 architecture slide here at FOSDEM
{{< /scene >}}
```

When Hugo sees the `scene` directive it will generate HTML code containing:

- The `<div>` and its special `scene` class
- The `title` inside the `h1` tag
- And the text inside the `scene` directive, interpreted as Markdown too:

```html
<div class="scene">
<h1>
  Resurecting Dinosaurs
</h1>
<p>
SPEAKER: I did <em>not</em> expect to have a win32 architecture slide
here at FOSDEM.
</p>
</div>
```

Finally, I have a bit of CSS to render the `div` properly:

```sass
.scene {
  font-family: monospace;
  line-height: 1.2em;

  h1 {
    line-height: 1.5em;
    font-size: 1.2em;
    font-style: bold;
    text-align: center;
  }
}
```

And that’s all there is to it :)

### Switching to a new theme

After a while, I was getting tired with `blackburn`. Its CSS files were not easy to edit, it also had big dependencies like `font-awesome` or Yahoo’s `Pure CSS`.

So I switched to [minio](https://themes.gohugo.io/minimo/), which is the theme I still use today. It uses `Sass` instead of pure `CSS`, and its sources are neatly organized. Plus, it comes with a nicely configured toolchain, which allows to get feedback on changes made to the theme instantly.

## Source organization

If you take a look at the [sources of the blog](https://github.com/dmerejkowsky/blog/tree/master/content/post) you will find posts are numbered chronologically:

```
0001-hello-world.md
0002-i-use-vim-and-so-should-you.md
0003-finding-a-good-project-name.md
...

```

I like this scheme for several reasons:

- Posts naturally appeared sorted everywhere (even with `ls`)
- I will get this nice feeling of accomplishment when I write my 100th post
- I can easily auto complete filenames from my editor (I just need to remember the post number)

Since I don’t really want the internal number to be seen outside, all the articles have a `slug` in the “front matter”:

```markdown
# In 0042-foo.md
---
slug: "foo"
date: "2016-03-31T13:00:19+00:00"
draft: false
title: "..."
---
```

This means the `0042-foo.md` file will get written as `foo/index.html`.

I also told `nginx` that `blog/post/foo` correspond to `blog/post/foo/index.html`:

```nginx
location /blog {
  try_files $uri $uri/index.html =404;
}
```

This is called _pretty URLs_ in Hugo’s documentation.

## Comments

The last piece of the puzzle is the comments system.

I use [isso](https://posativ.org/isso/), a self-hosted comment service.

First, I’ve patched the Hugo template to add a tiny bit of JavaScript at the bottom of every article:

```html
<!-- in layouts/entry.html -->
<div>
  <script data-isso="//dmerej.info/isso/"
            src="//dmerej.info/isso/js/embed.min.js"
  >
  </script>
  <section id="isso-thread">
  </section>
</div>
```

Then I made sure the `isso` service was reachable at `https://dmerej.info/isso`, with help from `nginx`:

```nginx
# In /etc/nginx/conf.d/blog.conf
location /isso {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Script-Name /isso;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_pass http://localhost:1234;
}
```

and `systemd`:

```ini
# In isso.service
[Unit]
Description=isso comments service
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
ExecStart=/srv/isso/.local/bin/isso -c /srv/isso/isso.conf run
User=isso

[Install]
WantedBy=multi-user.target
```

Some notes:

- The comment form does not show if the visitor has disabled JavaScript. I find that a bit sad, but on the other hand it keeps robots from posting spam (at least so far).
- All the comments are stored in a SQLite database. I have a systemd timer to back it up every day.
- People can opt-in to leave their e-mail in the form. Isso does nothing with it but store them in its database. I sometimes use them to send them private messages.

So that’s how the blog works under the hood! Stay tuned for part 2, where I’ll explain how new articles get written and published.

---


_I'd love to hear what you have to say, so please feel free to leave a comment below, or check out [my contact page](https://dmerej.info/blog/pages/contact/) for more ways to get in touch with me._