Tweaking a Nikola Theme

I adjusted the default Nikola theme to show cover images!
Motivation
I am a visual person. You might not know that from all the typing and my enthusiasm for command line tools. But many of my posts and pages have cover images. Sometimes the cover images are even relevant to the post.
In the live site, cover images are prominently displayed at the top of their pages. They get referenced when a post gets shared on social media. A cropped and adjusted version of the cover image gets displayed in post summaries.
So if I’m using Nikola to build something like my current site, I need cover images.
Nikola site uses the bootblog4 theme by default, taking advantage of the Bootstrap toolkit. bootblog4 doesn’t support cover images, so I’ll make a version that does.
Mind you, I don’t want to build a whole new theme. That can come later. There’s even a nice tutorial for creating a theme. For now I just want to tweak the default a little.
Set up files and metadata
Nikola starts with a few assumptions I can work with. bootblog4 already
looks for previewimage
metadata to build
thumbnails for featured
posts. Nikola also
expects to find image files in your site’s images/
folder. Makes
sense.
I’ll mirror the content path with images, and add previewimage
metadata which points to the right spot.
posts/2019/12/again-with-the-manual-symmetry/index.md
---
date: 2019-12-15 12:37:51-08:00
tags:
- drawing
- Procreate
- symmetry
title: Again with the manual symmetry
category: note
previewimage: /images/2019/12/again-with-the-manual-symmetry/cover.jpg
---
Hugo uses a powerful but sometimes confusing taxonomy system in layout customization. Nikola prefers a powerful but sometimes confusing “theme inheritance” system. Look. They’re all confusing. It’s just a matter of finding the kind of confusing you don’t mind.
With theme inheritance, my tweaks are a new theme. But the new theme basically says “I’m like that theme, except that I changed these templates.”
So let’s inherit a theme.
Nikola’s theme
command
Option | Description |
---|---|
-i ARG, --install=ARG |
Install a theme. (config: install) |
-r ARG, --uninstall=ARG |
Uninstall a theme. (config: uninstall) |
-l, --list |
Show list of available themes. (config: list) |
--list-installed |
List the installed themes with their location. (config: list_installed) |
-u ARG, --url=ARG |
URL for the theme repository (default: https://themes.getnikola.com/v8/themes.json) (config: url) |
-g ARG, --get-path=ARG |
Print the path for installed theme (config: getpath) |
-c ARG, --copy-template=ARG |
Copy a built-in template into templates/ or your theme (config: copy-template) |
-n ARG, --new=ARG |
Create a new theme (config: new) |
--engine=ARG |
Engine to use for new theme (mako or jinja – default: mako) (config: new_engine) |
--parent=ARG |
Parent to use for new theme (default: base) (config: new_parent) |
--legacy-meta |
Create legacy meta files for new theme (config: new_legacy_meta) |
So I ask Nikola for a new theme, using bootblog4 as the parent.
$ nikola theme --new rgb-bootblog4 --parent bootblog4
...
[2020-01-21T15:35:33Z] NOTICE: theme: Remember to set THEME="rgb-bootblog4" in conf.py to use this theme.
Because I didn’t specify a template engine, rgb-bootblog4 uses Mako.
Let’s remember to update conf.py
as directed, so we can see the
theme as we tweak it. The theme
tutorial also mentions
disabling USE_BUNDLES
during theme development. I thought they meant
page bundles for a second and got excited, until I realized
bundles meant
bundled JavaScript and CSS for quicker HTTP/1 downloads.
# Name of the theme to use.
THEME = "rgb-bootblog4"
USE_BUNDLES = False
Sweet. I have a new themes/rgb-bootblog4
folder. Wait. It has no
templates.
Oh that’s right. This is what they were talking about with template inheritance. The templates are still in the parent. It’s up to me to copy and change specific templates. That’s both good and a little risky when the parent theme updates. What if my tweak turns out to be incompatible? Okay, not going to worry about it today. If you’re going to veer wildly from the parent, you should probably use base as the parent.
Editing templates
So which of the built-in
templates do I
want? Since both posts and pages have cover images on my site, I’ll
start with the most general template. Everything starts with
base.tmpl
. Let’s look there.
$ nikola theme -c base.tmpl
Can I find anything interesting in the base template?
${template_hooks['page_header']()}
<%block name="extra_header"></%block>
<%block name="content"></%block>
Over here on the live site, I put cover images above the main content.
extra_header
looks promising. Where to set it? I prefer to make my
changes in the most relevant template instead of the most general.
Give me a minute to explore…
Okay. Pages ultimately inherit from posts — Mako supports template inheritance, letting the parent define some blocks while overriding others. We might be able to do this with one change.
$ nikola theme -c post.tmpl
Nikola provides a large number of template
variables to work with,
but today I focus on post
. How about the preview image? It gets set in
post metadata, so I could use post.meta("previewimage")
. Don’t have
to do that though. previewimage
metadata is important enough that it
gets promoted to an attribute of the post
object.
post.tmpl
<%block name="extra_header">
% if post.previewimage:
<div class="figure">
<img src="${post.previewimage}" alt="${post.title}" width="1000">
<p class="caption">${post.title()}</p>
</figure>
% endif
</%block>
Keep in mind what I noticed the other day about these not being real figures in reStructuredText. For now I match RST output, as if I’d used a figure directive. That way I don’t have to find the CSS for this theme.
It has a cover image, placed right by the title. It doesn’t quite match today’s view of that post, but this has the basic idea. And I only had to edit a single template file!
Looks good for posts that have a cover image. How about pages?
Excellent. I thought that would take much more work.
Remember Bootstrap?
bootblog4 is based off of Bootstrap. I feel compelled to make the cover image a Jumbotron.
<%block name="extra_header">
% if post.previewimage:
<div class="figure jumbotron">
<img src="${post.previewimage}" alt="${post.title}" width=1000>
<p class="caption">${post.title()}</p>
</div>
% endif
</%block>
Hm. Maybe, maybe not. I’m tempted to tweak it some more, but my task list is long and my time is short.
Did I miss anything?
Sort of. On the live site, I let Hugo resize cover images to fit in my design and avoid large downloads. Nikola has thumbnails, but that’s not quite the same thing. I’d have to do it myself, maybe with a plugin.