How to sneak in a static CMS

Posted on 2019-09-24 by Nico Schottelius


To put you in the right mood for reading this article, I ask you take some assumptions for reading this article:

Assume you are the CEO of a small IPv6, Linux and FOSS company. Assume that some years ago you made the decision to use Django CMS Blog for the blog to support non-technical staff to post blog articles.

Also, for the sake of completeness, assume that you are still running your own private blog with ikiwiki.


I believe that before changing anything (especially in IT), you should have a good reason for changing. So what could be the reason for sneaking in a static CMS? The answer is relatively easy:

  • Reducing latency
  • Reducing latency
  • Reducing the inhibition threshold for writing blog articles

Let's have a look at each of the points in detail, before letting us convince ourselves....

Reducing latency

One of the biggest problems for me is to wait for an web application to save something. With Django CMS Blog, you have the standard write - save - publish flow. So when I want to see the result, I have to wait seconds. Depending on my distance to our blog this might take 1 second (Europe) or about 5 seconds (South Korea). While this does not sound like much, it feels very long.

While google apps (which we don't use for our blog) like google drive (which has other issues as well) take a different approach in autosaving, this also blocks if you have a weak network link.

While it is just a few seconds, it is a huge difference between just being able to write in emacs (yes I was converted from vim) versus writing in a browser, waiting for the website to return.

Reducing latency

While editing with "high" latency is a problem of the writer, latency while loading the result is a metric that directly affects the readers feeling about a website. If it takes too long to a website, you, dear reader, are about to leave this website very fast. Even if I write the greatest and best content, you won't like it.

So by switching to a static CMS, the dynamic processing time is removed and pages can load as fast as the round trip time (RTT) between the web server and you.

Reducing the inhibition threshold for writing blog articles

Let's come to the third and maybe most important point: reducing the inhibition threshold for writing blog articles. Let's put some background into this: we are a small, Swiss based hosting company loving open source. However, the emphasises is on small.

So we cannot (nor do we want to ) afford huge marketing / adwork / paid advertisements. But our strategy is to do good and talk about it.

However if the barrier for writing and publishing is high, we won't write much about the things we do. And I think with a static CMS, geeks (like me) are having a much easier time to actually write a blog entry.

How to do it

Now let's have a look on how to sneak in a static CMS into an existing company website. is powered by our Django CMS based CMS (full source code is online).

The Django instance is running behind nginx, which allows us to proxy different parts of the website to different backends and to serve static assets directly from the filesystem.

On the other hand we have a static web server named that hosts various static pages.

The existing URLs of should all stay as they are without any conflict. For this reason the new static cms is placed at /u/. The static pages are generated on a client machine and are uploaded using the following Makefile snippet:


all: publish

publish: build permissions
    rsync -av $(BUILDDIR)/ $(DESTINATION)

permissions: build
    find $(BUILDDIR) -type f -exec chmod 0644 {} \;
    find $(BUILDDIR) -type d -exec chmod 0755 {} \;

    lektor build -O $(BUILDDIR)

The last step to sneak in the CMS was to modify the nginx configuration of with the following snippet:

    location /u/ {

What's next?

As you can see in this post, the design does not fully (cough) fit the regular design of However Lektor uses jinja2, which is very similar to what we already use in the existing dynamicweb project.

If you want to join the discussion about this, I invite you to our open chat on

And next in this blog: how to use it ;-)