Nikola is a static site and blog generator. So is Jekyll. While I like what we have done with Nikola,
I do admit that Jekyll (and others!) have many more, and nicer themes than Nikola does.

This document is an attempt at making it easier for 3rd parties (that means you people! ;-) to
create themes. Since I suck at designing websites, I asked for opinions on themes to port,
and got some feedback. Since this is Not So Hard™, I will try to make time to port a few
and see what happens.

Open the sidebar by default, or on a per-page basis by using its metadata

Let’s try to make all those nice things survive the porting.

Starting From Somewhere

Nikola has a nice, clean, base theme from which you can start when writing your own theme.
Why start from that instead of from a clean slate? Because theme inheritance is going to save you a ton of work,
that’s why. If you start from scratch you won’t be able to build anything until you have a bunch of
templates written. Starting from base, you just need to hack on the things you need to change.

First, we create a site with some content in it. We’ll use the nikola init wizard (with the --demo option) for that:

$ nikola init --demo lanyon-port
Creating Nikola Site
====================
This is Nikola v7.8.0. We will now ask you a few easy questions about your new site.
If you do not want to answer and want to go with the defaults instead, simply restart with the `-q` parameter.
--- Questions about the site ---
Site title [My Nikola Site]:
Site author [Nikola Tesla]:
Site author's e-mail [[email protected]]:
Site description [This is a demo site for Nikola.]:
Site URL [https://example.com/]:
--- Questions about languages and locales ---
We will now ask you to provide the list of languages you want to use.
Please list all the desired languages, comma-separated, using ISO 639-1 codes. The first language will be used as the default.
Type '?' (a question mark, sans quotes) to list available languages.
Language(s) to use [en]:
Please choose the correct time zone for your blog. Nikola uses the tz database.
You can find your time zone here:
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Time zone [UTC]:
Current time in UTC: 16:02:07
Use this time zone? [Y/n]
--- Questions about comments ---
You can configure comments now. Type '?' (a question mark, sans quotes) to list available comment systems. If you do not want any comments, just leave the field blank.
Comment system:
That's it, Nikola is now configured. Make sure to edit conf.py to your liking.
If you are looking for themes and addons, check out https://themes.getnikola.com/ and https://plugins.getnikola.com/.
Have fun!
[2015-05-28T16:02:08Z] INFO: init: A new site with example data has been created at lanyon-port.
[2015-05-28T16:02:08Z] INFO: init: See README.txt in that folder for more information.

Then, we create an empty theme inheriting from base. This theme will use Mako templates. If you prefer Jinja2,
then you should use base-jinja as a parent and jinja as engine instead:

Edit conf.py and set THEME = 'lanyon'. Also set USE_BUNDLES = False (just do it for now, we’ll get to bundles later).
Also, if you intend to publish your theme on the Index, or want to use it with older versions (v7.8.5 or older), use the --legacy-meta option for nikola theme -n.

You can now build that site using nikola build and it will look like this:

This is just the base theme.

Basic CSS

The next step is to know exactly how Lanyon’s pages work. To do this, we read its HTML.
First let’s look at the head element:

Notice I am not copying syntax.css? That’s because Nikola handles that styles for syntax highlighting
in a particular way, using a setting called CODE_COLOR_SCHEME where you can configure
what color scheme the syntax highlighter uses. You can use your own assets/css/code.css if you
don’t like the provided ones.

Nikola requiresassets/css/rst_base.css and assets/css/code.css to function properly.
We will also add themes for Jupyter (assets/css/ipython.min.css
and assets/css/nikola_ipython.css) into the template; note that they are
activated only if you configured your POSTS/PAGES with ipynb support.
There’s also assets/css/nikola_rst.css, which adds Bootstrap 3-style reST notes etc.

But how do I tell our lanyon theme to use those CSS files instead of whatever it’s using now?
By giving our theme its own base_helper.tmpl.

That file is a template used to generate parts of the pages. It’s large and
complicated but we don’t need to change a lot of it. First, make a copy in your
theme (note this command requires setting your THEME in conf.py to
lanyon):

You may say this looks like crap. Don’t worry, we are just starting :-)

Page Layout

This is trickier but should be no problem for people with a basic understanding of HTML and a desire to make a theme!

Lanyon’s content is split in two parts: a sidebar and the rest. The sidebar looks like this (shortened for comprehension):

<body><!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular styles, `#sidebar-checkbox` for behavior. --><inputtype="checkbox"class="sidebar-checkbox"id="sidebar-checkbox"><!-- Toggleable sidebar --><divclass="sidebar"id="sidebar"><divclass="sidebar-item"><p>A reserved <ahref="http://jekyllrb.com"target="_blank">Jekyll</a> theme that places the utmost gravity on content with a hidden drawer. Made by <ahref="https://twitter.com/mdo"target="_blank">@mdo</a>.</p></div><navclass="sidebar-nav"><aclass="sidebar-nav-item active"href="/">Home</a><aclass="sidebar-nav-item"href="/about/">About</a> [...]
</nav></div>

So, a plain body, with an input element that controls the sidebar, a div which is the sidebar itself.
Inside that, div.sidebar-item for items, and a nav with "navigational links". This is followed by the "masthead" and
the content itself, which we will look at in a bit.

That link which says "Skip to main content" is very important for accessibility, so we will leave it in
place. But below, you can see how it creates the "container" div we see in the Nikola page, and the content is
created by html_header() which is defined in base_header.tmpl The actual nav element is done
by the html_navigation_links function out of the NAVIGATION_LINKS option.

So, first, lets change that base template to be more lanyon-like:

## -*- coding: utf-8 -*-<%namespacename="base"file="base_helper.tmpl"import="*"/><%namespacename="header"file="base_header.tmpl"import="*"/><%namespacename="footer"file="base_footer.tmpl"import="*"/>${set_locale(lang)}${base.html_headstart()}<%blockname="extra_head">### Leave this block alone.</%block>${template_hooks['extra_head']()}</head><body><ahref="#content"class="sr-only sr-only-focusable">${messages("Skip to main content")}</a><!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular styles, `#sidebar-checkbox` for behavior. --><inputtype="checkbox"class="sidebar-checkbox"id="sidebar-checkbox"><!-- Toggleable sidebar --><divclass="sidebar"id="sidebar"><divclass="sidebar-item"><p>A reserved <ahref="http://getnikola.com"target="_blank">Nikola</a> theme that places the utmost gravity on content with a hidden drawer. Made by <ahref="https://twitter.com/mdo"target="_blank">@mdo</a> for Jekyll,
ported to Nikola by <ahref="https://twitter.com/ralsina"target="_blank">@ralsina</a>.</p></div>${header.html_navigation_links()}</div><mainid="content"role="main"><%blockname="content"></%block></main>${footer.html_footer()}${body_end}${template_hooks['body_end']()}${base.late_load_js()}</body></html>

And that’s after I exposed the sidebar by clicking on an invisible widget!

One problem, which causes that yellow color in the sidebar is a CSS conflict.
We are loading rst_base.css which specifies
the background color of div.sidebar which is more specific than
lanyon.css, which specifies for .sidebar alone.

There are many ways to fix this, I chose to change lanyon.css to also use div.sidebar:

Note: this means this theme will not support submenus in navigation. If you want that, I’ll happily take a patch.

Starting to see a resemblance?

Now let’s look at the content. In Lanyon, this is how the "main" content looks:

<!-- Wrap is the content to shift when toggling the sidebar. We wrap the content to avoid any CSS collisions with our real content. --><divclass="wrap"><divclass="masthead"><divclass="container"><h3class="masthead-title"><ahref="/"title="Home">Lanyon</a><small>A Jekyll theme</small></h3></div></div><divclass="container content"><divclass="post"><h1class="post-title">Introducing Lanyon</h1><spanclass="post-date">02 Jan 2014</span><p>Lanyon is an unassuming <ahref="http://jekyllrb.com">Jekyll</a> theme [...]
</div></div></div><labelfor="sidebar-checkbox"class="sidebar-toggle"></label></body></html>

Everything inside the "container content" div is… the content. The rest is a masthead with the site title
and at the bottom a label for the sidebar toggle. Easy to do in base.tmpl
(only showing the relevant part):

<!-- Wrap is the content to shift when toggling the sidebar. We wrap the content to avoid any CSS collisions with our real content. --><divclass="wrap"><divclass="masthead"><divclass="container"><h3class="masthead-title"><ahref="/"title="Home">Lanyon</a><small>A Jekyll theme</small></h3></div></div><divclass="container content"id="content"><%blockname="content"></%block></div></div><labelfor="sidebar-checkbox"class="sidebar-toggle"></label>${footer.html_footer()}${body_end}${template_hooks['body_end']()}${base.late_load_js()}</body></html>

Getting there!

The sidebar looks bad because of yet more CSS conflicts with rst_base.css. By
adding some extra styling in lanyon.css, it will look better.

Also, the accessibility link on top is visible when it should not. That’s
because we removed theme.css from the base theme, and with it, we lost a
couple of classes. We can add them in lanyon.css, along with others used by other
pieces of the site:

One clear problem is that the title "Lanyon · A Jekyll theme" is set in the
theme itself. We don’t do that sort of thing in Nikola, we have settings for
that. So, let’s use them. There is a html_site_title function in
base_helper.tmpl which is just the thing. So we change base.tmpl to use it:

As for the actual content, that’s not in any of the templates we have seen so far. The page you see is an
"index.tmpl" page, which means it’s a list of blog posts shown one below the
other. Obviously it’s not doing
things in the way the Lanyon CSS expects it to. Here’s the original, which you
can find in Nikola’s source
code:

Customization

The original Lanyon theme supports some personalization options. It suggests you do them by tweaking the templates, and
you can also do that in the Nikola port. But we prefer to use options for that, so that you can get a later, better
version of the theme and it will still "just work".

Let’s see the color schemes first. They apply easily, just tweak your body element like this:

<bodyclass="theme-base-08">...
</body>

We can tweak base.tmpl to do just that:

%iflanyon_subtheme:<bodyclass="${lanyon_subtheme}">%else:<body>%endif

And then we can put the options in conf.py’s GLOBAL_CONTEXT:

GLOBAL_CONTEXT={"lanyon_subtheme":"theme-base-08"}

Look at it, all themed up.

Doing the same for layout-reverse, sidebar-overlay and the rest is left as an exercise for the reader.

Bundles

If you have webassets installed and the USE_BUNDLES option set to True, Nikola can put several CSS or JS files together in a larger file,
which makes sites load faster. To do that, your theme needs a bundles file where the syntax is:

Note: Some themes also support the USE_CDN option meaning that in some cases it will load one bundle with all CSS and in other will load some CSS files
from a CDN and others from a bundle. This is complicated and probably not worth the effort.

The End

And that’s it, that’s a whole theme. Eventually, once people start using it, they will notice small broken details, which will need handling one at a time.

What if you want to extend other parts of the theme? Check out the Theming reference. You can also contribute your improvements to the nikola-themes <https://github.com/getnikola/nikola> repository on GitHub.