skip to main content

Moving my blog to Lektor

Last year I decided it was time to move to a static blog.

At the time, I had already two blogs — one on blogger for 4 years and the other on tumblr for 9 years.

The tumblr blog started as a distraction in a low point of my life. I spent a good amount of time discovering great stuff including, but not limited to, photography, programming and humor. What started as a distraction remained one and I never was able to use that plaform to be productive while discovering all that stuff. So at some point, I got a blogger blog.

Over the last four years (2012 - 2016), I wrote about 40 posts on the blogger blog and removed most of them. The removed posts were just unremarkable stuff in the hindsight. Most of the posts that remained did not have good content. They were okay. The plans I published on what I wanted to do, which are now removed, didn't work mostly because of my goal-oriented approach. I decided to move toward a systems-oriented approach to achieve consistency and continuity in my plans. One other thing that helped me was that blogger was uninspiring and unmodern. Though better, Wordpress fell in the same bucket for me.

The other option was to build a static blog.

Why static?

Static sites have a few advantages over dynamic blogs depending on what is desired. Among other advantages, I like that static sites are super fast, much secure and versionable.


Static pages have really good page load speeds.

In one instance, an article on my site with the most content took around 192ms with cache disabled. The associated styles and web fonts took about 338ms. Disqus comments and Google analytics took just about 1s. Since some of these requests happened in parallel, the overall page load completed in 1.12 seconds. Each run had a different result, but the page load completed around that 1.2 - 1.5s range.

This is all when the cache is empty. The second and subsequent loads will be even faster. Some tests even showed 500ms total time for the entire page to load.

I admit that the scenario will change a bit when there are a few images, but even then the page loads will be significantly faster than its dynamic counterpart.

It is quite easy to see 90/100 scores on most speed testing websites.


A site is dynamic when every user request is handled on-the-fly. When the user wants to see a list of a certain category of pages, the server routes that request to the blog engine which understands the request and fetches the list from a database. If the user wants to view the images in a cool lightbox gallery, the blog engine provides that by employing a plugin or two.

The more the features a dynamic blog uses, the more the attack surface that is exposed. In the above two scenarios, we have the server, the blog engine, the database and any and all of the plugins, called attack vectors, open for attack. An attack can really manifest in the form of some new kind a hack or simply from something like lack of maintenance of a plugin or by not applying a security patch on one of the attack vectors.

The only attack surface a static site generally has is the server. All it takes is to maintain and monitor the server well and you are safer.

If you use something like Github pages or Gitlab pages, you wouldn't need to worry about the server as well. These companies employ more robust techniques to secure their server. The only thing you would have to worry is about your content. Putting it in a better way, the only thing you would have to focus on is your content.


You put the static site inside a version control and work on it like any other project. In a regular dynamic blog, the content resides in a database. In a static site, the content resides in flat files along with the configuration and the code. You write an article in your text editor, commit it and push it to the central repository just like you would a feature or bug fix in your regular projects. Then the act of pushing the commit to the central repo will trigger an automatic deploy or a build and deploy to the server. This is convenient. In my case, I push a commit to the server and automatically a gitlab CI job is triggered that builds and deploys the content to the server.

If you chose to put your site in a public repository, anyone can see the history of the post including all the edits and the way the content is shaped into to its current form. Users can create a PR to suggest an edit or correction or major update to your blog post or article. They can also simply create an issue on your repository to raise a bug or fix to the article/blog or to just open a dialogue on the said article/blog. I have come across a few static bloggers who encourage commenting on an article entirely through the way of the Github issues. I think that is very cool.


There are also a few trade-offs with a static site.

  • Static sites are not for non-technical users due to initial setup and the process involved.
  • No or limited admin.
  • Limited plugin availability

So while static sites are not everyone, if you are the adventurous type, you can give static sites a try.

Enter Lektor.

Why Lektor?

As a Python enthusiast, I had to choose between Pelican and Nikola and the more recent ones, Urubu and Lektor. As I explored these four static site generators, I realized all of them were very capable and powerful in their own ways.

However, Lektor felt the right fit for me for the following reasons.

Simple folder hierarchy

Folder hierarchy:


These are the key folders:

  1. assets folder has styles and images
  2. the content folder has articles and sub sections
  3. models contain data models which can create a type of page or a set of pages and set attributes for pages
  4. templates contain HTML templates and macros for reusable HTML fragments

The files at the root of each folder are just markdown files that Lektor expects to build into the index.html for that folder.

No language based configuration

As a developer, I don't mind messing with code and language based configuration files. As a content author, I want to deal only with flat files. I do not want to mess around with code.

There is an obvious overlap between the personas, a developer, and a content author since often you fix some feature to accommodate some new content or a scenario for a new article. Since this happens quite often, I handle this as a workflow task rather than mixing both personas.

Data modeling

Data models allow us to create a representation of a specific HTML output. Each model will have a few base fields like the name and description. We can extend the models somewhat to create systems like navigation, pagination, and possibly even more.

We will see how models are used when we walk through the configuration and customization of a static blog .

Convenient CLI tool

Lektor comes with a neat CLI tool that helps us create, build, serve and deploy projects. Lektor CLI has fewer commands than its counterparts.

Type lektor and see the available commands. I use two commands most of the time, lektor server, to serve the content locally, and lektor build, to download packages if needed and build the content.

Each command comes with a good amount of documentation. Simply append --help at the end of a command like this:

lektor build --help

This gives a nice help text with all the switches you could use with the lektor build command.


So, thanks to gitlab pages and Lektor, I have a new home for my blogging activities. Over the next few months, I will keep busy with the following activities:

  1. Importing select posts from previous blogs
  2. Enhancing Lektor functionalities.

These are the unordered and unprioritized list of todos for this blog at the moment.

  1. post drafts - Feb 02 2019
  2. post series - Jan 13 2019
  3. recent / related posts
  4. introduce webpack
  5. rss feed - Jan 15 2017
  6. tags - Aug 02 2017