I decided to migrate this website/blog from Lektor to Nikola. Both are static site generators implemented in Python that allow you to generate a static, secure, and maintenance-free website/blog. Here is my experience, why I did it, how to do it, and what to expect. In short: While I liked Lektor for its simplicity, it lacked several features I needed. So far, Nikola has these features and many more which is why I'm very happy to have switched. Read the rest of the pros and cons here.
Both Lektor and Nikola are Static Site Generators (SSG) implemented in Python. You basically create everything on your computer and the the generator generates HTML which can be hosted on GitHub or almost everywhere without any hassle. Besides, it's blazing fast, secure, and needs no server configuration/maintenance. Find an overview at Full Stack Python.
When I created this website, I chose Lektor for it's simplicity. Compared to Wordpress, which I had used before, it was easy to set up and maintain.
Again, this is highly opinionated.
I basically set up a clean Nikola project and then adapted my old content. Here's what I did with a rough time estimation:
If you're also getting started, here are the issues I ran into. As I said, not many and not frustrating :)
While there are a few basic and advanced themes you can build upon, it took me quite some time to find out where these themes can be found. This is necessary to understand which files there are and which files you need to overwrite to adapt a theme. Basically most templates you can inherit from can be found at nikola-themes but some basic templates are stored within Nikola itself. If you've understood this, you basically just copy/paste the files you want to adapt inside your own theme which works really nice.
Since I had previously set up Lektor deployment via GitHub Pages, I already had a gh-pages
branch.
So when I tried to deploy via nikola github_deploy
, I got the following error:
To github.com:lorey/karllorey.com.git
! [rejected] gh-pages -> gh-pages (fetch first)
error: failed to push some refs to 'git@github.com:lorey/karllorey.com.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
# .stacktrace
[2020-02-25T15:12:28Z] ERROR: github_deploy: Failed GitHub deployment -- command ['ghp-import', '-n', '-m', 'Nikola auto commit.\n\nSource commit: 5d74f162affaf80691de1d7c7b0d8728addea96a\nNikola version: 8.0.4', '-p', '-r', 'origin', '-b', 'gh-pages', 'output'] returned 1
Obviously, I forgot to pull the gh-pages branch first, so the new commit could be added on top.
After doing a git pull origin gh-pages
, deploying worked like a charm.
To deploy with Travis CI, there's a great post on the Nikola blog.
What I did not understand at first was the distinction between the master
and a src
branch.
So the src
branch is used for user pages that are deployed into the master branch, i.e. when you have a site pointing to you username, e.g. lorey.github.io
.
If you do that, you have to use another branch to deploy to avoid an infinite loop (push to master > deploy to master > ...).
Since I use gh-pages
as the branch containing all the generated HTML, I set up .travis.yml to deploy on pushes to master.
In the conf.py
I still set:
GITHUB_SOURCE_BRANCH = 'src'
Seems to work fine.
Another thing I encountered when setting up Travis CI:
Somehow the travis gem had issues when logging in so travis login
and travis enable
did not work.
Maybe because I use an old version or have 2FA enabled.
In the end I just ran travis encrypt-file id_rsa --add
which worked fine and added a line to .travis.yml
storing the encrypted key.
Doing a git branch master FETCH_HEAD
inside the .travis.yml failed:
$ git branch master FETCH_HEAD
fatal: A branch named 'master' already exists.
The command "git branch master FETCH_HEAD" failed and exited with 128 during .