Switching to Nikola!

This might be a shock to many of you (except my boyfriend and his roommate, who have been giving me sh*t about this forever), but before today I actually hard-coded my website. This meant that every time I updated a post, changed my resume, etc., I had to hard code the changes and the ripple effects.

What was I thinking. Honestly. You can look at how painful it was here on GitLab. I kept it as a reminder and in case I severely messed up this whole Nikola thing, which I'm going to explain in the bulk of this post.

I actually made a lot of changes, starting with dumping my old website host, Bluehost. I had decided to register my domain names on Google Domains, which was not only half the cost of Bluehost -- $50/year on Bluehost for 2 domains, and $24/year on Google Domains for the same -- but it provided an easier interface to fix settings, play with email stuff (you can get at me via vicky[AT]vickysteeves[DOT]com so cool!!), and have domains connected to a Google account, which is just convenient. It's all around really great. If Google retires this, I will honestly throw a fit.

So after I had made the change from Bluehost to Google Domains, I made the switch from Bluehost's servers to GitLab. I exported my site (which was still just hard-coded, even back then) and uploaded to a private GitLab repository. I wanted to make it look pretty before I made it public, as I was pretty embarrassed that I still hard-coded my site, especially given I have a C.S. degree... shame.

So I also knew that I couldn't hard-code forever. It was such a hassle to update everything manually every time I wanted to write a post. Rémi pointed me towards static site generators, which I had never really heard of before. This introduction to SSGs was really helpful to me as I decided to go with this option. Some of the most obvious advantages are:

  • Completely open-source development
    • The static site generators I considered are fully open source, which lets people not only develop great themes and plugins, but support each other in building/using/customizing the generator.
    • Anyone can file an issue on my site or blog posts (or help me do development -- shoutout to Rémi for that already) when something is wrong or to add a correction with a pull request.
  • Easy version control and integration with GitLab, which I had already chosen to host my website.
  • Speed: static generators are usually much faster than a full-blown content mangement system (CMS) like WordPress or the like, because it doesn't rely on a database and server configuration.
  • Ease of Use: I don't have to deal with a server, which I don't really need. I just need to serve up my HTML pages! And if need be, I can migrate the site to something else -- as a data management librarian, I always have to have an exit strategy ;)

I eventually opened up an issue in my GitLab repo that put pressure on me to make this change happen. Static Gen was an invaluable resource to me as I narrowed my choices down to eventually include Nikola. Nikola is actually #26 on this list, which ranks SSGs by the number of stars it has on GitLab, but it was a really obvious choice for me. I had a few requirements for a site generator:

  • Support Bootstrap themes/JS, which I love and already had been using.
  • Simple blogging framework
  • Preferably python based

I narrowed it down to Pelican, Hugo, Lektor, and Nikola. Each had their obvious advantages: Pelican is really simple to build, Hugo is really fast and allows users to define their own metadata, Lektor has built-in dependency tracking, but Nikola stood out to me for a few reasons: built-in Boostrap & Bootswatch support, amazing plugins (including one to send your posts to the Internet Archive!), a really active user and development community, translatable (like French for my boyfriend's parents, who like to Google me :P), python 2 and 3 compatiable, and beyond easy to build.

The next step was to actually take the plunge and develop it. Because Nikola was developed with a "blog first" mentality, I had to do some interesting things with the configuration file to make sure I could my homepage and resume page, and THEN my blog on it's own separate page. Nikola's developers have a good guide for doing this. The default setup for pages and posts in Nikola's conf.py file is::

POSTS = (
	("posts/*.rst", "posts", "post.tmpl"),
	("posts/*.txt", "posts", "post.tmpl"),
	("posts/*.html", "posts", "post.tmpl"),
	)

	PAGES = (
	    ("stories/*.rst", "stories", "story.tmpl"),
	    ("stories/*.txt", "stories", "story.tmpl"),
	    ("stories/*.html", "stories", "story.tmpl"),
	)

We have to modify this to look like::

POSTS = ()

	PAGES = (
	("stories/*.rst", "", "story.tmpl"),
	("stories/*.txt", "", "story.tmpl"),
	("stories/*.html", "", "story.tmpl"),
	)

	INDEX_PATH = "blog"

And then add the pages in the folder called "stories" which is basically Nikola-speak for just regular web pages. After I was done adding the pages I wanted (basically a home page and a resume page, basically copy-pasting what I had on my original site), I reviewed the POSTS to look like this::

POSTS = (
	    ("posts/*.rst", "blog", "post.tmpl"),
	    ("posts/*.txt", "blog", "post.tmpl"),
	    ("posts/*.html", "blog", "post.tmpl"),
	)

And all the posts would be indexed on a new page called "Blog" which I then added to my navigation, along with my recently added pages.

After getting the navigation and blog configured the way I wanted, the most labour-intensive part of the process began: porting over all my blog posts. Another amazing thing about Nikola, and another reason I chose it, is because users can write blog posts in whatever they want. This is my list from my conf.py file::

COMPILERS = {
	"rest": ('.rst', '.txt'), #reStructured Text
	"markdown": ('.md', '.mdown', '.markdown'), 
	"textile": ('.textile',),
	"txt2tags": ('.t2t',),
	"bbcode": ('.bb',),
	"wiki": ('.wiki',),
	"ipynb": ('.ipynb',), #iPython notebooks
	"html": ('.html', '.htm'),
	)

This worked out excellently for me because all my previous posts were written in HTML (again, I was being a n00b and hard-coding these all myself). I could literally copy and paste the body of the post, and clean up what needed to be cleaned. This included: fixing links to images and other parts of my website, and adding in the metadata that Nikola required. I had to fix my posts to follow this structure, which was super easy::

<!--
	.. title: Title of the Post!
	.. slug: pretty-url-slug
	.. date: 20XX-XX-XX
	.. tags: 
	.. category: 
	.. link: https://gitlab.com/VickySteeves/personal-website/blob/master/posts/{POST FILE NAME}
	.. description: 
	.. type: text
	-->
	<!DOCTYPE html>
	<html lang="en">
	  <body>
	      <!--POST BODY-->
	  </body>
	</html>`

After the posts were all successfully modified to the Nikola schema, it was a simple matter of cleaning up the aesthetics. This was done by copy-pasting the templates from Nikola into my site's directory, and then editing them -- the same as creating a child-theme in WordPress. By doing this, I could modify the way my site rendered dynamically. My favourite modification I made (and again, thanks to Rémi for the suggestion) was adding the GitLab source link on each of my blog posts. Each of my posts has this cute little GitLab image

image

at the far-right to the title, that, if clicked, brings the user to the source hosted on GitLab.

This allows my readers to go directly to the source of my post to make corrections, pull requests, etc. I did this by editing the post_header.tmpl file. I copied it into a folder in my site's directory called "templates" which has a long file path: personal-website/themes/custom/templates. Before editing, it just asked the post for it's metadata after displaying the title::

<%def name="html_post_header()">
	    <header>
		${html_title()}
		<div class="metadata">

After editing, the image was added to the right of the title. The code looks like this::

<%def name="html_post_header()">
	<header>
	{* GITLAB IMAGE WITH SOURCE LINK *}
	<a href="${post.meta('link')}" id="sourcelink"><img src="../../images/gitlab.png" height="5%" width="5%" style="float:right;"></a>
	    ${html_title()}
	    <div class="metadata">

This works by querying the post's metadata (which you saw above in the HTML template snippet) for the "link," which goes back to the GitLab source. I added some inline CSS (the style="") which isn't the cleanest, but hey -- it works, and if you want to fix it, make a pull request ;)

After adding this feature and cleaning up the aesthetics, Rémi made the excellent point that I should use Travis CI to make sure my site updated every time a commit was made, either through Git or on GitLab natively (PR or in-browser editing). He actually ended up writing my build file because engineers and he's super smart and did it in 2 seconds when it would have taken me a day.

This is my first post written and published using pure Nikola. I wrote it in reStructured Text format, which honestly seems like the biggest challenge in switching. After writing HTML for so long, it's an easy habit to get into. This is much nicer because it doesn't require tags for literally everything.

I hope this helps anyone else looking to make the switch into static site generators!