Theming Nikola

Version: 5
Author: Roberto Alsina <ralsina@netmanagers.com.ar>

Contents

This document is a reference about themes. If you want a tutorial, please read Creating a Theme

The Structure

Themes are located in the themes folder where Nikola is installed, one folder per theme. The folder name is the theme name.

A Nikola theme consists of three folders:

assets

This is where you would put your CSS, Javascript and image files. It will be copied into output/assets when you build the site, and the templates will contain references to them.

The included themes use Bootstrap and Colorbox so they are in assets, along with CSS files for syntax highligting and reStructuredText, and a minified copy of jQuery.

If you want to base your theme on other frameworks (or on no framework at all) just remember to put there everything you need for deployment.

templates
This contains the templates used to generate the pages. While Nikola will use a certain set of template names by default, you can add others for specific parts of your site.
messages
Nikola tries to be multilingual. This is where you put the strings for your theme so that it can be translated into other languages.

And these optional files:

parent

A text file that, on its first line, contains the name of the parent theme. Any resources missing on this theme, will be looked up in the parent theme (and then in the grandparent, etc).

The parent is so you don't have to create a full theme each time: just create an empty theme, set the parent, and add the bits you want modified.

engine
A text file which, on the first line, contains the name of the template engine this theme needs. Currently supported values are "mako" and "jinja". If this file is not given, "mako" is assumed.
bundles

A text file containing a list of files to be turned into bundles using WebAssets. For example:

assets/css/all.css=bootstrap.css,bootstrap-responsive.css,rst.css,code.css,colorbox.css,custom.css

This creates a file called "assets/css/all.css" in your output that is the combination of all the other file paths, relative to the output file. This makes the page much more efficient because it avoids multiple connections to the server, at the cost of some extra difficult debugging.

WebAssets supports bundling CSS and JS files.

Templates should use either the bundle or the individual files based on the use_bundles variable, which in turn is set by the USE_BUNDLES option.

Templates

In templates there is a number of files whose name ends in .tmpl. Those are the theme's page templates. They are done usig the Mako or Jinja2 template languages. If you want to do a theme, you should learn one first. What engine is used by the theme is declared in the engine file.

The rest of this document explains Mako templates, but Jinja2 is fairly similar.

Mako has a nifty concept of template inheritance. That means that, a template can inherit from another and only change small bits of the output. For example, base.tmpl defines the whole layout for a page but has only a placeholder for content so post.tmpl only define the content, and the layout is inherited from base.tmpl.

These are the templates that come with the included themes:

base.tmpl

This template defines the basic page layout for the site. It's mostly plain HTML but defines a few blocks that can be re-defined by inheriting templates:

  • extra_head is a block that is added before </head>, (ex: for adding extra CSS)
  • belowtitle is used by default to display a list of translations but you can put anything there.
  • content is where the inheriting templates will place the main content of the page.
  • permalink is an absolute path to the page (ex: "/archive/index.html")

This template always receives the following variables you can use:

  • lang is the laguage for this page.

  • title is the page's title.

  • description is the page's description.

  • blog_title is the blog's title.

  • blog_author is the blog's author.

  • messages contains the theme's strings and translations.

  • _link is an utility function to create links to other pages in the site. It takes three arguments, kind, name, lang:

    kind is one of:

    • tag_index (name is ignored)
    • tag (and name is the tag name)
    • tag_rss (name is the tag name)
    • archive (and name is the year, or None for the main archive index)
    • index (name is the number in index-number)
    • rss (name is ignored)
    • gallery (name is the gallery name)

    The returned value is always an absolute path, like "/archive/index.html".

  • rel_link converts absolute paths to relative ones. You can use it with _link and permalink to create relative links, which makes the site able to work when moved inside the server. Example: rel_link(permalink, url)

  • Anything you put in your GLOBAL_CONTEXT option in dodo.py. This usually includes sidebar_links, search_form, and others.

    The included themes use at least these:

    • rss_link a link to custom RSS feed, although it may be empty)
    • blog_url the URL for your site
    • blog_title the name of your site
    • content_footer things like copyright notices, disclaimers, etc.
    • license a larger license badge
    • analytics google scripts, or any JS you want to tack at the end of the body of the page.
    • disqus_forum: a Disqus ID you can use to enable comments.

It's probably a bad idea to do a theme that requires more than this (please put a README in it saying what the user should add in its dodo.py), but there is no problem in requiring less.

post.tmpl

Template used for blog posts. Can use everything base.tmpl uses, plus:

  • post: a Post object. This has a number of members:
    • post.title(language): returns a localized title
    • post.date
    • post.tags: A list of tags
    • post.text(language): the translated text of the post
    • post.permalink(language, absolute): Link to the post in that language. If absolute is True the link contains the full URL. This is useful for things like Disqus comment forms.
    • post.next_post is None or a Post object that is next newest in the timeline.
    • post.prev_post is None or a Post object that is next oldest in the timeline.
story.tmpl
Used for pages that are not part of a blog, usually a cleaner, less intrusive layout than post.tmpl, but same parameters.
gallery.tmpl

Template used for image galleries. Can use everything base.tmpl uses, plus:

  • text: A descriptive text for the gallery.
  • images: A list of (thumbnail, image) paths.
index.tmpl

Template used to render the multipost indexes. Can use everything base.tmpl uses, plus:

  • posts: a list of Post objects, as described above.
  • prevlink: a link to a previous page
  • nextlink: a link to the next page
list.tmpl

Template used to display generic lists of links. Can use everything base.tmpl uses, plus:

  • items: a list of (text, link) elements.
list_post.tmpl

Template used to display generic lists of links. Can use everything base.tmpl uses, plus:

  • posts: a list of Post objects.

You can add other templates for specific pages, which the user can the use in his post_pages option in dodo.py. Also, keep in mind that your theme is yours, there is no reason why you would need to maintain the inheritance as it is, or not require whatever data you want.

Messages and Translations

When you modify templates, you may want to add text in them (for example: "About Me"). Instead of adding the text directly, which makes it impossible to translate to other languages, add it like this:

${messages[lang]["About Me"]}

Then, in messages/en.py add it along the other strings:

MESSAGES = [
    u"Posts for year %s",
    u"Archive",
    u"Posts about %s:",
    u"Tags",
    u"Also available in: ",
    u"More posts about",
    u"Posted:",
    u"Original site",
    u"Read in english",
    u"About Me",
]

Then, when I want to use your theme in spanish, all I have to do is add a line in messages/es.py:

MESSAGES = {
    u"LANGUAGE": u"Español",
    u"Posts for year %s": u"Posts del año %s",
    u"Archive": u"Archivo",
    u"Posts about %s:": u"Posts sobre %s",
    u"Tags": u"Tags",
    u"Also available in: ": u"También disponible en: ",
    u"More posts about": u"Más posts sobre",
    u"Posted:": u"Publicado:",
    u"Original site": u"Sitio original",
    u"Read in english": u"Leer en español",
    u"About Me": u"Acerca del autor",
}

And voilá, your theme works in spanish. Don't remove strings from these files even if it seems your theme is not using them. Some are used internally in Nikola to generate titles and similar things.

To create a new translation, just copy one of the existing ones, translate the right side of every string to your language, save it and send it to me, I will add it to Nikola!