The Nikola Handbook

::: {.alert .alert-info .pull-right} ::: {.contents} ::: :::

All You Need to Know

After you have Nikola installed:

Create a empty site (with a setup wizard):

nikola init mysite

You can create a site with demo files in it with nikola init --demo mysite

The rest of these commands have to be executed inside the new mysite folder.

Create a post:

nikola new_post

Edit the post:

The filename should be in the output of the previous command.

Build the site:

nikola build

Start the test server:

nikola serve

See the site:

That should get you going. If you want to know more, this manual will always be here for you.


On the other hand, if anything about Nikola is not as obvious as it should be, by all means tell me about it :-)

What\'s Nikola and what can you do with it?

Nikola is a static website and blog generator. The very short explanation is that it takes some texts you wrote, and uses them to create a folder full of HTML files. If you upload that folder to a server, you will have a rather full-featured website, done with little effort.

It\'s original goal is to create blogs, but it supports most kind of sites, and can be used as a CMS, as long as what you present to the user is your own content instead of something the user generates.

Nikola can do:

  • A blog (example)
  • Your company\'s site
  • Your personal site
  • A software project\'s site (example)
  • A book\'s site

Since Nikola-based sites don\'t run any code on the server, there is no way to process user input in forms.

Nikola can\'t do:

  • Twitter
  • Facebook
  • An Issue tracker
  • Anything with forms, really (except for comments!)

Keep in mind that \"static\" doesn\'t mean boring. You can have animations, slides or whatever fancy CSS/HTML5 thingie you like. It only means all that HTML is generated already before being uploaded. On the other hand, Nikola sites will tend to be content-heavy. What Nikola is good at is at putting what you write out there.

Getting Help

::: {.lead} Get help here! :::


Why Static?

Most \"modern\" websites are dynamic in the sense that the contents of the site live in a database, and are converted into presentation-ready HTML only when a user wants to see the page. That\'s great. However, it presents some minor issues that static site generators try to solve.

In a static site, the whole site, every page, everything, is created before the first user even sees it and uploaded to the server as a simple folder full of HTML files (and images, CSS, etc).

So, let\'s see some reasons for using static sites:


Dynamic sites are prone to experience security issues. The solution for that is constant vigilance, keeping the software behind the site updated, and plain old good luck. The stack of software used to provide a static site, like those Nikola generates, is much smaller (Just a web server).

A smaller software stack implies less security risk.


If you create a site using (for example) WordPress, what happens when WordPress releases a new version? You have to update your WordPress. That is not optional, because of security and support issues. If I release a new version of Nikola, and you don\'t update, nothing happens. You can continue to use the version you have now forever, no problems.

Also, in the longer term, the very foundations of dynamic sites shift. Can you still deploy a blog software based on Django 0.96? What happens when your host stops supporting the php version you rely on? And so on.

You may say those are long term issues, or that they won\'t matter for years. Well, I believe things should work forever, or as close to it as we can make them. Nikola\'s static output and its input files will work as long as you can install a Python 2.7/3.3 or newer under Linux, Windows, or OS X and can find a server that sends files over HTTP. That\'s probably 10 or 15 years at least.

Also, static sites are easily handled by the Internet Archive.

Cost and Performance

On dynamic sites, every time a reader wants a page, a whole lot of database queries are made. Then a whole pile of code chews that data, and HTML is produced, which is sent to the user. All that requires CPU and memory.

On a static site, the highly optimized HTTP server reads the file from disk (or, if it\'s a popular file, from disk cache), and sends it to the user. You could probably serve a bazillion (technical term) pageviews from a phone using static sites.


On server-side blog platforms, sometimes you can\'t export your own data, or it\'s in strange formats you can\'t use in other services. I have switched blogging platforms from Advogato to PyCs to two homebrew systems, to Nikola, and have never lost a file, a URL, or a comment. That\'s because I have always had my own data in a format of my choice.

With Nikola, you own your files, and you can do anything with them.


Nikola has a very defined feature set: it has every feature I needed for my own sites. Hopefully, it will be enough for others, and anyway, I am open to suggestions.

If you want to create a blog or a site, Nikola provides:

  • Front page (and older posts pages)
  • RSS Feeds
  • Pages and feeds for each tag you used
  • Custom search
  • Full yearly archives
  • Custom output paths for generated pages
  • Easy page template customization
  • Static pages (not part of the blog)
  • Internationalization support (my own blog is English/Spanish)
  • Google sitemap generation
  • Custom deployment (if it\'s a command, you can use it)
  • A (very) basic look and feel you can customize, and is even text-mode friendly
  • The input format is light markup (reStructuredText or Markdown)
  • Easy-to-create image galleries
  • Support for displaying source code
  • Image slideshows
  • Client-side cloud tags


  • A preview web server
  • \"Live\" re-rendering while you edit
  • \"Smart\" builds: only what changed gets rebuilt (usually in seconds)
  • Easy to extend with minimal Python knowledge.

Installing Nikola

This is currently lacking on detail. Considering the niche Nikola is aimed at, I suspect that\'s not a problem yet. So, when I say \"get\", the specific details of how to \"get\" something for your specific operating system are left to you.

The short version is:

pip install nikola

Note that you need Python v2.7 or newer OR v3.3 or newer.

Some features require extra dependencies. You can install them all in bulk by doing:

pip install nikola[extras]

Alternatively, you can install those packages one-by-one, when required (Nikola will tell you what packages are needed)

After that, run nikola init --demo sitename and that will run the setup wizard, which will create a folder called sitename containing a functional demo site.

Nikola is packaged for some Linux distributions, you may get that instead. e.g. If you are running Arch Linux, there are AUR packages, available in Python 2/3 and stable/git master flavors: python-nikola / python2-nikola for the latest stable release or python-nikola-git / python2-nikola-git for the GitHub master. (only one package may be installed at the same time.)

libxml/libxslt (files missing) errors

If you get errors about various files missing while compiling lxml, you must install headers for the libxml, libxslt and zlib libraries, like so:

Debian systems:

sudo apt-get install libxml2-dev libxslt1-dev zlib1g-dev

Red Hat/RPM-based systems:

sudo yum install libxslt-devel libxml2-devel zlib-devel

Python.h not found

If you get an error to the effect of Python.h not found, you need to install development packages for Python.

Debian systems:

sudo apt-get install python-dev

Red Hat/RPM-based systems:

sudo yum install python-devel

Note that many other distros/operating systems (including Arch Linux, *BSD and OS X) do not require such packages, as C headers are included with the base distribution of Python.

Installation on Linux/Mac OS X/etc.

(any POSIX-compatible OS will do.)

Using pip should suffice. You may also want to use distribution- or system-specific packages for our dependencies.

There are no known issues or caveats on those OSes. Keep in mind that most of our developers run Linux on a daily basis and may not have the full knowledge required to resolve issues relating to your operating system.

Installation on Windows and Windows support

Nikola supports Windows! Keep in mind, though, that there are some caveats:

  1. lxml and Pillow require compiled extensions. Compiling them on Windows is hard for most people. Fortunately, compiled packages exist. Check their PyPI pages to find official packages, the unofficial Gohlke binaries site, or get them somewhere else. If you are using virtualenvs, using those pre-built packages is possible through virtualenv --system-site-packages.
  2. Windows has some differences over POSIX, which may cause some features to work incorrectly under Windows. If any problems occur, please do not hesitate to report them. Some of the differences include:
    • \ as path separator (instead of /)
    • the concept of HDD partitions and letters (instead of seamless mounting under one root)
    • some characters in paths are disallowed (although this shouldn't cause problems)
    • CR+LF (aka \r\n) as the line separator (instead of LF \n)
  3. Most of our developers run Linux on a daily basis and may not have the full knowledge required to resolve issues relating to Windows.

Getting Started

To create posts and pages in Nikola, you write them in one of the supported input formats. Those source files are later converted to HTML The recommended formats are reStructuredText and Markdown, but there is also support for textile and WikiCreole and even for just writing HTML.

::: {.note} ::: {.admonition-title} Note :::

There is a great quick tutorial to learn reStructuredText. :::

First, let\'s see how you \"build\" your site. Nikola comes with a minimal site to get you started.

The tool used to do builds is called doit, and it rebuilds the files that are not up to date, so your site always reflects your latest content. To do our first build, just run \"nikola build\":

$ nikola build
Scanning posts....done!
.  render_posts:stories/manual.html
.  render_posts:posts/1.html
.  render_posts:stories/1.html
.  render_archive:output/2012/index.html
.  render_archive:output/archive.html
.  render_indexes:output/index.html
.  render_pages:output/posts/welcome-to-nikola.html
.  render_pages:output/stories/about-nikola.html
.  render_pages:output/stories/handbook.html
.  render_rss:output/rss.xml
.  render_sources:output/stories/about-nikola.txt

Nikola will print a line for every output file it generates. If we do it again, that will be much much shorter:

$ nikola build
Scanning posts....done!

That is because doit is smart enough not to generate all the pages again, unless you changed something that the page requires. So, if you change the text of a post, or its title, that post page, and all index pages where it is mentioned, will be recreated. If you change the post page template, then all the post pages will be rebuilt.

Nikola is mostly a series of doit tasks, and you can see them by doing nikola list:

$ nikola list
Scanning posts....done!

You can make Nikola redo everything by calling nikola forget and then nikola build (or nikola build -a, you can make it do just a specific part of the site using task names, for example nikola build render_pages, and even individual files like nikola build output/index.html

Nikola also has other commands besides build:

$ nikola help
Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit

Available commands:
  nikola auto                 automatically detect site changes, rebuild and optionally refresh a browser
  nikola bootswatch_theme     given a swatch name from and a parent theme, creates a custom theme
  nikola build                run tasks
  nikola check                check links and files in the generated site
  nikola clean                clean action / remove targets
  nikola console              start an interactive Python console with access to your site
  nikola deploy               deploy the site
  nikola doit_auto            automatically execute tasks when a dependency changes
  nikola dumpdb               dump dependency DB
  nikola forget               clear successful run status from internal DB
  nikola github_deploy        deploy the site to GitHub pages
  nikola help                 show help
  nikola ignore               ignore task (skip) on subsequent runs
  nikola import_wordpress     import a WordPress dump
  nikola init                 create a Nikola site in the specified folder
  nikola install_theme        install theme into current site
  nikola list                 list tasks from dodo file
  nikola new_page             create a new page in the site
  nikola new_post             create a new blog post or site page
  nikola orphans              list all orphans
  nikola plugin               manage plugins
  nikola serve                start the test webserver
  nikola strace               use strace to list file_deps and targets
  nikola tabcompletion        generate script for tab-completion
  nikola version              print the Nikola version number

  nikola help                 show help / reference
  nikola help <command>       show command usage
  nikola help <task-name>     show task usage

The serve command starts a web server so you can see the site you are creating:

$ nikola serve -b
Serving HTTP on port 8000 ...

After you do this, a web browser opens at and you should see the sample site. This is useful as a \"preview\" of your work.

By default, the serve command runs the web server on port 8000 on the IP address You can pass in an IP address and port number explicitly using -a IP_ADDRESS (short version of --address) or -p PORT_NUMBER (short version of --port) Example usage:

$ nikola serve --address --port 8080
Serving HTTP on port 8080 ...

Creating a Blog Post

To create a new post, the easiest way is to run nikola new_post. You will be asked for a title for your post, and it will tell you where the post\'s file is located.

By default, that file will contain also some extra information about your post (\"the metadata\"). It can be placed in a separate file by using the -2 option, but it\'s generally easier to keep it in a single location.

The contents of your post have to be written (by default) in reStructuredText but you can use a lot of different markups using the -f option.

Currently Nikola supports reStructuredText, Markdown, IPython Notebooks, HTML as input, can also use Pandoc for conversion, and has support for BBCode, CreoleWiki, txt2tags, Textile and more via plugins.

You can control what markup compiler is used for each file extension with the COMPILERS option. The default configuration expects them to be placed in posts but that can be changed (see below, the POSTS and PAGES options)

This is how it works:

$ nikola new_post
Creating New Post

Enter title: How to make money
Your post's text is at:  posts/how-to-make-money.txt

The content of that file is as follows:

.. title: How to make money
.. slug: how-to-make-money
.. date: 2012-09-15 19:52:05 UTC
.. tags:
.. link:
.. description:
.. type: text

Write your post here.

The slug is the page name. Since often titles will have characters that look bad on URLs, it\'s generated as a \"clean\" version of the title. The third line is the post\'s date, and is set to \"now\".

The other lines are optional. Tags are comma-separated. The link is an original source for the content, and description is mostly useful for SEO. type is the post type, whatever you set here (prepended with post-) will become a CSS class of the <article> element for this post. Defaults to text (resulting in a post-text class)

You can add your own metadata fields in the same manner, if you use a theme that supports them (for example: .. author: John Doe)

To add these metadata fields to all new posts by default, you can set the variable ADDITIONAL_METADATA in your configuration. For example, you can add the author metadata to all new posts by default, by adding the following to your configuration:

    'author': 'John Doe'

::: {.sidebar} Other Metadata Fields

Nikola will also use other metadata fields:


Author of the post, will be used in the RSS feed and possibly in the post display (theme-dependent)

annotations / noannotations

Override the value of the ANNOTATIONS option for this specific post or page.


Like tags, except each post can have only one, and they usually have more descriptive names.


Set \"True\" if you do not want to see the page title as a heading of the output html file (does not work for posts).


Set to \"True\" to disable comments. Example:

.. nocomments: True

The post will be encrypted and invisible until the reader enters the password. Also, the post\'s sourcecode will not be available.

WARNING: DO NOT use for real confidential data. The algorithm used (RC4) is insecure. The implementation may also be easily brute-forced. Please consider using something else if you need real encryption!

More information: Issue #1547


Designate a preview or other representative image path relative to BASE_URL for use with Open Graph for posts. Adds the image when sharing on social media and many other uses.

The image can be of any size and dimension (services will crop and adapt) but should less than 1 MB and be larger than 300x300 (ideally 600x600).


Will change the template used to render this page/post specific page. Example:

.. template: story.tmpl

That template needs to either be part of the theme, or be placed in a templates/ folder inside your site. :::

::: {.note} ::: {.admonition-title} Note :::

The Two-File Format

Nikola originally used a separate .meta file. That will still work! The format of the meta files is the same as shown above (i.e. only the 7 base fields, in the order listed above), but without the explanations:

How to make money
2012-09-15 19:52:05 UTC

However, starting with Nikola v7, you can now use .meta files and put all metadata you want, complete with the explanations --- they look just like the beginning of our reST files.

Both file formats are supported; however, the new format is preferred, if possible. :::

If you are writing a multilingual site, you can also create a per-language post file (for example: with the default TRANSLATIONS_PATTERN, see below). This one can replace metadata of the default language, for example:

  • The translated title for the post or page
  • A translated version of the page name

The pattern used for finding translations is controlled by the TRANSLATIONS_PATTERN variable in your configuration file.

The default is to put the language code before the file extension, so the German translation of some_file.rst should be named This is because the TRANSLATIONS_PATTERN variable is by default set to:

TRANSLATIONS_PATTERN = "{path}.{lang}.{ext}"

::: {.note} ::: {.admonition-title} Note :::

Considered languages

Nikola will only look for translation of input files for languages specified in the TRANSLATIONS variable. :::

You can edit these files with your favourite text editor, and once you are happy with the contents, generate the pages as explained in Getting Started

Currently supported languages are:

  • Basque
  • Bulgarian
  • Catalan
  • Chinese (Simplified)
  • Croatian
  • Czech
  • Dutch
  • English
  • Esperanto
  • Estonian
  • Finnish
  • French
  • German
  • Greek
  • Hindi
  • Italian
  • Japanese
  • Norwegian Bokmål
  • Persian
  • Polish
  • Portuguese (Brasil)
  • Russian
  • Slovak
  • Slovene
  • Spanish
  • Turkish
  • Urdu

If you wish to add support for more languages, check out the instructions at the theming guide.

The post page is generated using the post.tmpl template, which you can use to customize the output.

The place where the post will be placed by new_post is based on the POSTS and PAGES configuration options:

# POSTS and PAGES contains (wildcard, destination, template) tuples.
# The wildcard is used to generate a list of reSt source files
# (whatever/thing.txt).
# That fragment could have an associated metadata file (whatever/thing.meta),
# and optionally translated files (example for Spanish, with code "es"):
#     whatever/ and whatever/
#     This assumes you use the default TRANSLATIONS_PATTERN.
# From those files, a set of HTML fragment files will be generated:
# cache/whatever/thing.html (and maybe cache/whatever/
# These files are combined with the template to produce rendered
# pages, which will be placed at
# output / TRANSLATIONS[lang] / destination / pagename.html
# where "pagename" is the "slug" specified in the metadata file.
# The difference between POSTS and PAGES is that POSTS are added
# to feeds and are considered part of a blog, while PAGES are
# just independent HTML pages.

    ("posts/*.txt", "posts", "post.tmpl"),
    ("posts/*.rst", "posts", "post.tmpl"),
    ("stories/*.txt", "stories", "story.tmpl"),
    ("stories/*.rst", "stories", "story.tmpl"),

new_post will use the first path in POSTS (or PAGES if -p is supplied) that ends with the extension of your desired markup format (as defined in COMPILERS in as the directory that the new post will be written into. If no such entry can be found, the post won't be created.

The new_post command supports some options:

$ nikola help new_post
Purpose: Create a new blog post or site page.
Usage:   nikola new_post [options] [path]

  -p, --page                Create a page instead of a blog post.
  -t ARG, --title=ARG       Title for the page/post.
  --tags=ARG                Comma-separated tags for the page/post.
  -1                        Create post with embedded metadata (single file format)
  -2                        Create post with separate metadata (two file format)
  -f ARG, --format=ARG      Markup format for post, one of rest, markdown, wiki, bbcode, html, textile, txt2tags

The optional path parameter tells nikola exactly where to put it instead of guessing from your config. So, if you do nikola new_post posts/random/foo.txt you will have a post in that path, with \"foo\" as its slug.


You may not want to show the complete content of your posts either on your index page or in RSS feeds, but to display instead only the beginning of them.

If it\'s the case, you only need to add a \"magical comment\" in your post.

In reStructuredText:


In Markdown (or basically, the resulting HTML of any format):

<!-- TEASER_END -->

By default all your RSS feeds will be shortened (they\'ll contain only teasers) whereas your index page will still show complete posts. You can change this behaviour with your INDEX_TEASERS defines whether index page should display the whole contents or only teasers. RSS_TEASERS works the same way for your RSS feeds.

By default, teasers will include a \"read more\" link at the end. If you want to change that text, you can use a custom teaser:

.. TEASER_END: click to read the rest of the article

Or you can completely customize the link using the READ_MORE_LINK option:

# A HTML fragment with the Read more... link.
# The following tags exist and are replaced for you:
# {link}        A link to the full post page.
# {read_more}   The string “Read more” in the current language.
# {{            A literal { (U+007B LEFT CURLY BRACKET)
# }}            A literal } (U+007D RIGHT CURLY BRACKET)
# READ_MORE_LINK = '<p class="more"><a href="{link}">{read_more}…</a></p>'


If you add a \"draft\" tag to a post, then it will not be shown in indexes and feeds. It will be compiled, and if you deploy it it will be made available, so use with care. If you wish your drafts to be not available in your deployed site, you can set DEPLOY_DRAFTS = False in your configuration.

Also if a post has a date in the future, it will not be shown in indexes until you rebuild after that date. This behaviour can be disabled by setting FUTURE_IS_NOW = True in your configuration, which will make future posts be published immediately. Posts dated in the future are not deployed by default (when FUTURE_IS_NOW = False). To make future posts available in the deployed site, you can set DEPLOY_FUTURE = True in your configuration. Generally, you want FUTURE_IS_NOW and DEPLOY_FUTURE to be the same value.

Private (formerly retired) Posts

If you add a \"private\" tag to a post, then it will not be shown in indexes and feeds. It will be compiled, and if you deploy it it will be made available, so it will not generate 404s for people who had linked to it.

Queuing Posts

Some blogs tend to have new posts based on a schedule (for example, every Mon, Wed, Fri) but the blog authors don\'t like to manually schedule their posts. You can schedule your blog posts based on a rule, by specifying a rule in the SCHEDULE_RULE in your configuration. You can either post specific blog posts according to this schedule by using the --schedule flag on the new_post command or post all new posts according to this schedule by setting SCHEDULE_ALL = True in your configuration. (Note: This feature requires that the FUTURE_IS_NOW setting is set to False)

For example, if you would like to schedule your posts to be on every Monday, Wednesday and Friday at 7am, add the following SCHEDULE_RULE to your configuration :


For more details on how to specify a recurrence rule, look at the iCal specification.

Say, you get a free Sunday, and want to write a flurry of new posts, or at least posts for the rest of the week, you would run the new_post command with the --schedule flag, as many times as you want:

$ nikola new_post --schedule
# Creates a new post to be posted on Monday, 7am.
$ nikola new_post -s
# Creates a new post to be posted on Wednesday, 7am.
$ nikola new_post -s
# Creates a new post to be posted on Friday, 7am.

All these posts get queued up according to your schedule, but note that you will anyway need to build and deploy your site for the posts to appear online. You can have a cron job that does this regularly.

Post Types

Nikola supports specifying post types, just like Tumblr does. Post types affect the look of your posts, by adding a post-YOURINPUTHERE CSS class to the post. Each post can have one and exactly one type. Nikola styles the following types in the default themes:

Name(s) Description Styling

text plain text --- default value standard

micro "small" (short) posts big serif font

Creating a Page

Pages are the same as posts, except that:

  • They are not added to the front page
  • They don\'t appear on the RSS feed
  • They use the story.tmpl template instead of post.tmpl by default

The default configuration expects the page\'s metadata and text files to be on the stories folder, but that can be changed (see PAGES option above).

You can create the page\'s files manually or use the new_post command with the -p option, which will place the files in the folder that has use_in_feed set to False.


If you need a page to be available in more than one place, you can define redirections in your

# A list of redirection tuples, [("foo/from.html", "/bar/to.html")].
# A HTML file will be created in output/foo/from.html that redirects
# to the "/bar/to.html" URL. notice that the "from" side MUST be a
# relative URL.
# If you don't need any of these, just set to []

REDIRECTIONS = [("index.html", "/weblog/index.html")]

It\'s better if you can do these using your web server\'s configuration, but if you can\'t, this will work.


The configuration file is called and can be used to customize a lot of what Nikola does. Its syntax is python, but if you don\'t know the language, it still should not be terribly hard to grasp.

The default you get with Nikola should be fairly complete, and is quite commented.

You surely want to edit these options:

# Data about this site
BLOG_AUTHOR = "Your Name"  # (translatable)
BLOG_TITLE = "Demo Site"  # (translatable)
BLOG_DESCRIPTION = "This is a demo site for Nikola."  # (translatable)

Some options are demarked with a (translatable) comment above or right next to them. For those options, two types of values can be provided:

  • a string, which will be used for all languages
  • a dict of language-value pairs, to have different values in each language

::: {.note} ::: {.admonition-title} Note :::

It is possible to load the configuration from another file by specifying --conf=path/to/other.file on Nikola\'s command line. For example, to build your blog using the configuration file configurations/test.config, you have to execute nikola build --conf=configurations/test.config. :::

Customizing Your Site

There are lots of things you can do to personalize your website, but let\'s see the easy ones!

CSS tweaking

Using the default configuration, you can create a assets/css/custom.css file under files/ or in your theme and then it will be loaded from the <head> blocks of your site pages. Create it and put your CSS code there, for minimal disruption of the provided CSS files.

If you feel tempted to touch other files in assets, you probably will be better off with a custom theme.

If you want to use LESS or Sass for your custom CSS, or the theme you use contains LESS or Sass code that you want to override, you will need to install the LESS plugin or SASS plugin create a less or sass directory in your site root, put your .less or .scss files there and a targets file containing the list of files you want compiled.

Template tweaking

If you really want to change the pages radically, you will want to do a custom theme.

Navigation Links

The NAVIGATION_LINKS option lets you define what links go in a sidebar or menu (depending on your theme) so you can link to important pages, or to other sites.

The format is a language-indexed dictionary, where each element is a tuple of tuples which are one of:

  1. A (url, text) tuple, describing a link
  2. A (((url, text), (url, text), (url, text)), title) tuple, describing a submenu / sublist.


        ('/archive.html', 'Archives'),
        ('/categories/index.html', 'Tags'),
        ('/rss.xml', 'RSS'),
        ((('/foo', 'FOO'),
          ('/bar', 'BAR')), 'BAZ'),

::: {.note} ::: {.admonition-title} Note :::

Support for submenus is theme-dependent. Only one level of submenus is supported. :::

::: {.note} ::: {.admonition-title} Note :::

Some themes, including the default Bootstrap 3 theme, may present issues if the menu is too large. (in bootstrap3, the navbar can grow too large and cover contents.) :::

::: {.note} ::: {.admonition-title} Note :::

If you link to directories, make sure to follow STRIP_INDEXES. If it's set to True, end your links with a /, otherwise end them with /index.html --- or else they won't be hilighted when active. :::

The SEARCH_FORM option contains the HTML code for a search form based on which should always work, but feel free to change it to something else.


CONTENT_FOOTER is displayed, small at the bottom of all pages, I use it for the copyright notice. The default shows a text formed using BLOG_AUTHOR, BLOG_EMAIL, the date and LICENSE. Note you need to use CONTENT_FOOTER_FORMATS instead of regular str.format or %-formatting, for compatibility with the translatable settings feature.


This option lets you define a HTML snippet that will be added at the bottom of body. The main usage is a Google analytics snippet or something similar, but you can really put anything there. Good place for JavaScript.


The SOCIAL_BUTTONS_CODE option lets you define a HTML snippet that will be added at the bottom of body. It defaults to a snippet for AddThis, but you can really put anything there. See [social_buttons.html]{.title-ref} for more details.

Fancy Dates

Nikola can use various styles for presenting dates.


The date format to use if there is no JS or fancy dates are off. Compatible with Python's strftime() syntax.


The date format to use if fancy dates are on. Compatible with moment.js syntax.


Fancy dates are off, and DATE_FORMAT is used.


Dates are recalculated in user's timezone. Requires JavaScript.


Dates are recalculated as relative time (eg. 2 days ago). Requires JavaScript.

In order to use fancy dates, your theme must support them. The built-in Bootstrap family supports it, but other themes might not by default.

For Mako:

``` {.sourceCode .html}

For Jinja2:

``` {.sourceCode .html}
<!-- required scripts -- best handled with bundles -->
<script src="/assets/js/moment-with-locales.min.js"></script>
<script src="/assets/js/fancydates.js"></script>

<!-- fancy dates code -->
moment.locale("{{ momentjs_locales[lang] }}");
fancydates({{ date_fanciness }}, {{ js_date_format }});
<!-- end fancy dates code -->

Adding Files

Any files you want to be in output/ but are not generated by Nikola (for example, favicon.ico) just put it in files/. Everything there is copied into output by the copy_files task. Remember that you can\'t have files that collide with files Nikola generates (it will give an error).

::: {.admonition} Important

Don\'t put any files manually in output/. Ever. Really. Maybe someday Nikola will just wipe output/ and then you will be sorry. So, please don\'t do that. :::

If you want to copy more than one folder of static files into output you can change the FILES_FOLDERS option:

# One or more folders containing files to be copied as-is into the output.
# The format is a dictionary of "source" "relative destination".
# Default is:
# FILES_FOLDERS = {'files': '' }
# Which means copy 'files' into 'output'

Getting More Themes

There are a few themes for Nikola. They are available at the Themes Index. Nikola has a built-in theme download/install mechanism to install those themes --- the install_theme command:

$ nikola install_theme -l

$ nikola install_theme blogtxt
[2013-10-12T16:46:13Z] NOTICE: install_theme: Downloading:
[2013-10-12T16:46:15Z] NOTICE: install_theme: Extracting: blogtxt into themes

And there you are, you now have themes/blogtxt installed. It\'s very rudimentary, but it should work in most cases.

If you create a nice theme, please share it! You can do it as a pull request in the GitHub repository.

One other option is to tweak an existing theme using a different color scheme, typography and CSS in general. Nikola provides a bootswatch_theme option to create a custom theme by downloading free CSS files from

$ nikola bootswatch_theme -n custom_theme -s spruce -p bootstrap3
[2013-10-12T16:46:58Z] NOTICE: bootswatch_theme: Creating 'custom_theme' theme
from 'spruce' and 'bootstrap3'
[2013-10-12T16:46:58Z] NOTICE: bootswatch_theme: Downloading:
[2013-10-12T16:46:58Z] NOTICE: bootswatch_theme: Downloading:
[2013-10-12T16:46:59Z] NOTICE: bootswatch_theme: Theme created. Change the THEME setting to "custom_theme" to use it.

You can even try what different swatches do on an existing site using their handy bootswatchlet

Play with it, there\'s cool stuff there. This feature was suggested by clodo.


Nikola doesn\'t really have a concept of deployment. However, if you can specify your deployment procedure as a series of commands, you can put them in the DEPLOY_COMMANDS option, and run them with nikola deploy.

You can have multiple deployment presets. If you run nikola deploy, the default preset is executed. You can also specify the names of presets you want to run (eg. nikola deploy default, multiple presets are allowed).

One caveat is that if any command has a % in it, you should double them.

Here is an example, from my own site\'s deployment script:

DEPLOY_COMMANDS = {'default': [
    'rsync -rav --delete output/',
    'rdiff-backup output ~/blog-backup',
    "links -dump ''",

Other interesting ideas are using git as a deployment mechanism (or any other VCS for that matter), using lftp mirror or unison, or Dropbox. Any way you can think of to copy files from one place to another is good enough.

Deploying to GitHub

Nikola provides a separate command github_deploy to deploy your site to GitHub pages. The command builds the site, commits the output to a gh-pages branch and pushes the output to GitHub. Nikola uses the ghp-import command \<> for this.

The branch to use for committing the sources can be changed using the GITHUB_DEPLOY_BRANCH option in your config. For a, this MUST be set to master, and the branch containing the sources must be changed to something else, like deploy, using the GITHUB_SOURCE_BRANCH option. The remote name to which the changes are pushed is origin by default, and can be changed using the GITHUB_REMOTE_NAME option. You also, obviously, need to have git on your PATH, and should be able to push to the repository specified as the remote.

This command performs the following actions, when it is run:

  1. Builds the site
  2. Commit the output folder to the GITHUB_DEPLOY_BRANCH to this branch.
  3. Push the branch to the remote specified in GITHUB_REMOTE_NAME!

Comments and Annotations

While Nikola creates static sites, there is a minimum level of user interaction you are probably expecting: comments.

Nikola supports several third party comment systems:

By default it will use DISQUS, but you can change by setting COMMENT_SYSTEM to one of \"disqus\", \"intensedebate\", \"livefyre\", \"moot\", \"googleplus\", \"facebook\" or \"isso\"

::: {.sidebar} COMMENT_SYSTEM_ID

The value of COMMENT_SYSTEM_ID depends on what comment system you are using and you can see it in the system\'s admin interface.

  • For DISQUS it\'s called the shortname
  • In IntenseDebate it\'s the IntenseDebate site acct
  • In LiveFyre it\'s the siteId
  • In Moot it\'s your username
  • For Google Plus, COMMENT_SYSTEM_ID need not be set, but you must verify your authorship
  • For Facebook, you need to [create an app \<>]{.title-ref} (turn off sandbox mode!) and get an App ID
  • For isso, it is the URL of isso (must be world-accessible and have a trailing slash, default http://localhost:8080/) :::

To use comments in a visible site, you should register with the service and then set the COMMENT_SYSTEM_ID option.

I recommend 3rd party comments, and specially DISQUS because:

1) It doesn\'t require any server-side software on your site 2) They offer you a way to export your comments, so you can take them with you if you need to. 3) It\'s free. 4) It\'s damn nice.

You can disable comments for a post by adding a \"nocomments\" metadata field to it:

.. nocomments: True

::: {.admonition} DISQUS Support

In some cases, when you run the test site, you won\'t see the comments. That can be fixed by adding the disqus_developer flag to the templates but it\'s probably more trouble than it\'s worth. :::

::: {.admonition} Moot Support

Moot doesn\'t support comment counts on index pages, and it requires adding this to your

``` {.sourceCode .python} BODY_END = """ """ EXTRA_HEAD_DATA = """ """

::: {.admonition}
Facebook Support

You need jQuery, but not because Facebook wants it (see Issue \#639).

An alternative or complement to comments are annotations. Nikola
integrates the annotation service provided by
[AnnotateIt.]( To use it, set the `ANNOTATIONS` option to
True. This is specially useful if you want feedback on specific parts of
your writing.

You can enable or disable annotations for specific posts or pages using
the `annotations` and `noannotations` metadata.

Annotations require JQuery and are therefore not supported in the base
theme. You can check bootstrap theme\'s `base.html` for details on how
to handle them in custom themes.

Image Galleries

To create an image gallery, all you have to do is add a folder inside
`galleries`, and put images there. Nikola will take care of creating
thumbnails, index page, etc.

If you click on images on a gallery, you should see a bigger image,
thanks to the excellent [colorbox](

The gallery pages are generated using the `gallery.tmpl` template, and
you can customize it there (you could switch to another lightbox instead
of colorbox, change its settings, change the layout, etc.).

Images to be used in normal posts can be placed in the `images` folder.
These images will be processed and have thumbnails created just as for
galleries, but will then be copied directly to the corresponding path in
the `output` directory, so you can reference it from whatever page you
like, most easily using the `thumbnail` reST extension. If you don\'t
want thumbnails, just use the `files` folder instead.

The `` options affecting images and gallery pages are these:

    # One or more folders containing galleries. The format is a dictionary of
    # {"source": "relative_destination"}, where galleries are looked for in
    # "source/" and the results will be located in
    # "OUTPUT_PATH/relative_destination/gallery_name"
    # Default is:
    GALLERY_FOLDERS = {"galleries": "galleries"}
    # One or more folders containing images. The format is again a dictionary of
    # {"source": "relative_destination"}. Images will be scaled down if necessary so
    # that neither width nor height is greater than MAX_IMAGE_SIZE and copied to
    # destination folder. A thumbnail will also be created in the same folder with
    # ``.thumbnail`` inserted in the file name before the file extension
    # (e.g. ``tesla.thumbnail.jpg``).
    IMAGE_FOLDERS = {'images': ''}
    # More image/gallery options:
    MAX_IMAGE_SIZE = 1280

If you add a file in `galleries/gallery_name/index.txt` its contents
will be converted to HTML and inserted above the images in the gallery
page. The format is the same as for posts.

If you add some image filenames in
`galleries/gallery_name/exclude.meta`, they will be excluded in the
gallery page.

If `USE_FILENAME_AS_TITLE` is True the filename (parsed as a readable
string) is used as the photo caption. If the filename starts with a
number, it will be stripped. For example `03_an_amazing_sunrise.jpg`
will be render as *An amazing sunrise*.

Here is a [demo gallery](/galleries/demo) of historic, public domain
Nikola Tesla pictures taken from [this

Post Processing Filters

You can apply post processing to the files in your site, in order to
optimize them or change them in arbitrary ways. For example, you may
want to compress all CSS and JS files using yui-compressor.

To do that, you can use the provided helper adding this in your

    from nikola import filters

    FILTERS = {
      ".css": [filters.yui_compressor],
      ".js": [filters.yui_compressor],

Where `filters.yui_compressor` is a helper function provided by Nikola.
You can replace that with strings describing command lines, or arbitrary
python functions.

If there\'s any specific thing you expect to be generally useful as a
filter, contact me and I will add it to the filters library so that more
people use it.

The currently available filters are:

::: {.sidebar}
**Creating your own filters**

You can use any program name that works in place as a filter, like
`sed -i` and you can use arbitrary python functions as filters, too.

If your program doesn\'t run in-place, then you can use Nikola\'s
runinplace function. For example, this is how the yui\_compressor filter
is implemented:

``` {.sourceCode .python}
def yui_compressor(infile):
    return runinplace(r'yui-compressor --nomunge %1 -o %2', infile)

You can turn any function into a filter using apply_to_file. As a silly example, this would make everything uppercase and totally break your website:

``` {.sourceCode .python} import string from nikola.filters import apply_to_file FILTERS = { ".html": [apply_to_file(string.upper)] }


:   **THIS FILTER HAS BEEN TURNED INTO A NOOP** and currently does


:   Compress CSS/JavaScript using [YUI


:   Compile, compress, and optimize JavaScript [Google Closure


:   Compress PNG files using [optipng](


:   Compress JPEG files using


:   Improve typography using

Optimizing Your Website

One of the main goals of Nikola is to make your site fast and light. So
here are a few tips we have found when setting up Nikola with Apache. If
you have more, or different ones, or about other web servers, please

1.  Use a speed testing tool. I used Yahoo\'s YSlow but you can use any
    of them, and it\'s probably a good idea to use more than one.
2.  Enable compression in Apache:

        AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript

3.  If even after you did the previous step the CSS files are not sent

        AddType text/css .css

4.  Optionally you can create static compressed copies and save some CPU
    on your server with the GZIP\_FILES option in Nikola.
5.  The webassets Nikola plugin can drastically decrease the number of
    CSS and JS files your site fetches.
6.  Through the filters feature, you can run your files through
    arbitrary commands, so that images are recompressed, JavaScript is
    minimized, etc.
7.  The USE\_CDN option offloads standard JavaScript and CSS files to a
    CDN so they are not downloaded from your server.

reStructuredText Extensions

Nikola includes support for a few directives and roles that are not part
of docutils, but which we think are handy for website development.


Nikola supports math input via MathJax. It uses the usual math roles and
directives of reStructuredText.

In order to use them in your posts, you **must** add the special
`mathjax` tag.

Inline mathematics (equivalent to single dollar signs or
backslash-parentheses in LaTeX) are produced using the
[math]{.title-ref} **role**:

Euler's formula: $e^{ix} = \cos x + i\sin x$

    Eulers formula: :math:`e^{ix} = \cos x + i\sin x`

Display mathematics (equivalent to double dollar signs or
backslash-brackets in LaTeX) are produced using the [math]{.title-ref}

$$\int \frac{dx}{1+ax}=\frac{1}{a}\ln(1+ax)+C$$

    .. math::

       \int \frac{dx}{1+ax}=\frac{1}{a}\ln(1+ax)+C


This directive lets you embed media from a variety of sites
automatically by just passing the URL of the page. For example here are
two random videos:

    .. media::

    .. youtube::

It supports Instagram, Flickr, Github gists, Funny or Die, and dozens
more, thanks to [Micawber](


To link to a YouTube video, you need the id of the video. For example,
if the URL of the video is <>
what you need is **8N\_tupPBtWQ**

Once you have that, all you need to do is:

    .. youtube:: 8N_tupPBtWQ


To link to a Vimeo video, you need the id of the video. For example, if
the URL of the video is <> then the id is

Once you have that, all you need to do is:

    .. vimeo:: 20241459

If you have internet connectivity when generating your site, the height
and width of the embedded player will be set to the native height and
width of the video. You can override this if you wish:

    .. vimeo:: 20241459
       :height: 240
       :width: 320


This directive lets you share music from <> You
first need to get the ID for the piece, which you can find in the
\"share\" link. For example, if the WordPress code starts like this:

    [soundcloud url=""

The ID is 78131362 and you can embed the audio with this:

    .. soundcloud:: 78131362

You can also embed playlists, via the [soundcloud\_playlist]{.title-ref}
directive which works the same way.


The `code` directive has been included in docutils since version 0.9 and
now replaces Nikola\'s `code-block` directive. To ease the transition,
two aliases for `code` directive are provided: `code-block` and

    .. code-block:: python

       print("Our virtues and our failings are inseparable")


To use this, you have to put your source code files inside `listings` or
whatever folders your `LISTINGS_FOLDERS` variable is set to fetch files
from. Assuming you have a `` inside one of these folders:

    .. listing:: python

Will include the source code from ``, highlight its syntax in
python mode, and also create a `listings/` page (or in
another directory, depending on `LISTINGS_FOLDER`) and the listing will
have a title linking to it.

Listings support the same options [reST
support (including various options for controlling which parts of the
file are included), and also a `linenos` option for Sphinx

The `LISTINGS_FOLDER` configuration variable allows to specify a list of
folders where to fetch listings from together with subfolder of the
`output` folder where the processed listings should be put in. The
default is, `LISTINGS_FOLDERS = {'listings': 'listings'}`, which means
that all source code files in `listings` will be taken and stored in
`output/listings`. Extending `LISTINGS_FOLDERS` to
`{'listings': 'listings', 'code': 'formatted-code'}` will additionally
process all source code files in `code` and put the results into

::: {.note}
::: {.admonition-title}

Formerly, `start-at` and `end-at` options were supported; however, they
do not work anymore (since v6.1.0) and you should now use `start-after`
and `end-before`, respectively. You can also use `start-line` and


You can easily embed GitHub gists with this directive, like this:

    .. gist:: 2395294

Producing this:

::: {.gist}

This degrades gracefully if the browser doesn\'t support JavaScript.


To include an image placed in the `images` folder, use the `thumbnail`
directive, like this:

    .. thumbnail:: tesla.jpg

The small thumbnail will be placed in the page, and it will be linked to
the bigger version of the image when clicked, using
[colorbox]( by default. All options
supported by the reST
directive are supported (except `target`). If a body element is
provided, the thumbnail will mimic the behavior of the
directive instead:

    .. thumbnail:: tesla.jpg

       Nikola Tesla, the man that invented the 20th century.


To create an image slideshow, you can use the `slides` directive. For

    .. slides::



This directive is a thin wrapper around [Pygal]( and
will produce charts as SVG files embedded directly in your pages.

Here\'s an example of how it works:

    .. chart:: Bar
       :title: 'Browser usage evolution (in %)'
       :x_labels: ["2002", "2003", "2004", "2005", "2006", "2007"]

       'Firefox', [None, None, 0, 16.6, 25, 31]
       'Chrome',  [None, None, None, None, None, None]
       'IE',      [85.8, 84.6, 84.7, 74.5, 66, 58.6]
       'Others',  [14.2, 15.4, 15.3, 8.9, 9, 10.4]

The argument passed next to the directive (Bar in that example) is the
type of chart, and can be one of Line, StackedLine, Bar, StackedBar,
HorizontalBar, XY, DateY, Pie, Radar, Dot, Funnel, Gauge, Pyramid. For
examples of what each kind of graph is, [check

It can take *a lot* of options to let you customize the charts (in the
example, title and x\_labels). You can use any option described in [the
pygal docs](

Finally, the content of the directive is the actual data, in the form of
a label and a list of values, one series per line.


This role is useful to make links to other post or page inside the same

Here\'s an example:

    Take a look at :doc:`my other post <creating-a-theme>` about theme creating.

In this case we are giving the portion of text we want to link. So, the
result will be:

> Take a look at `my other post <creating-a-theme>`{.interpreted-text
> role="doc"} about theme creating.

If we want to use the post\'s title as the link\'s text, just do:

    Take a look at :doc:`creating-a-theme` to know how to do it.

and it will produce:

> Take a look at `creating-a-theme`{.interpreted-text role="doc"} to
> know how to do it.

Post List

This directive can be used to generate a list of posts. You could use
it, for example, to make a list of the latest 5 blog posts, or a list of
all blog posts with the tag `nikola`:

    Here are my 5 latest and greatest blog posts:

    .. post-list::
       :stop: 5

    These are all my posts about Nikola:

    .. post-list::
       :tags: nikola

The following options are recognized:


    `start` : integer

    :   The index of the first post to show. A negative value like `-3`
        will show the *last* three posts in the post-list. Defaults to


    `stop` : integer

    :   The index of the last post to show. A value negative value like
        `-1` will show every post, but not the *last* in the post-list.
        Defaults to None.


    `reverse` : flag

    :   Reverse the order of the post-list. Defaults is to not reverse
        the order of posts.


    `tags` : string \[, string\...\]

    :   Filter posts to show only posts having at least one of the

        Defaults to None.


    `slugs` : string \[, string\...\]

    :   Filter posts to show only posts having at least one of the
        `slugs`. Defaults to None.


    `all` : flag

    :   Shows all posts and pages in the post list. Defaults to show
        only posts with set *use\_in\_feeds*.


    `lang` : string

    :   The language of post *titles* and *links*. Defaults to default


    `template` : string

    :   The name of an alternative template to render the post-list.
        Defaults to `post_list_directive.tmpl`


    `id` : string

    :   A manual id for the post list. Defaults to a random name
        composed by `'post_list_' + uuid.uuid4().hex`.

The post list directive uses the `post_list_directive.tmpl` template
file (or another one, if you use the `template` option) to generate the
list\'s HTML. By default, this is an unordered list with dates and
clickable post titles. See the template file in Nikola\'s base theme for
an example of how this works.

Importing Your WordPress Site Into Nikola

If you like Nikola, and want to start using it, but you have a WordPress
blog, Nikola supports importing it. Here\'s the steps to do it:

1)  Get a XML dump of your site[^1]
2)  nikola import\_wordpress mysite.wordpress.2012-12-20.xml

After some time, this will create a `new_site` folder with all your
data. It currently supports the following:

-   All your posts and pages
-   Keeps \"draft\" status
-   Your tags and categories
-   Imports your attachments and fixes links to point to the right
-   Will try to add redirects that send the old post URLs to the new
-   Will give you a url\_map so you know where each old post was

    This is also useful for DISQUS thread migration!

-   Will try to convert the content of your posts. This is *not* error
    free, because WordPress uses some unholy mix of HTML and strange
    things. Currently we are treating it as markdown, which does a
    reasonable job of it.

    You will find your old posts in `new_site/posts/post-title.wp` in
    case you need to fix any of them.

This feature is a work in progress, and the only way to improve it is to
have it used for as many sites as possible and make it work better each
time, so I am happy to get requests about it.

Importing To A Custom Location Or Into An Existing Site

It is possible to either import into a location you desire or into an
already existing Nikola site. To do so you can specify a location after
the dump.:

    $ nikola import_wordpress  mysite.wordpress.2012-12-20.xml -o import_location

With this command Nikola will import into the folder `import_location`.

If the folder already exists Nikola will not overwrite an existing
``. Instead a new file with a timestamp at the end of the
filename will be created.

Using Twitter Cards

Nikola supports Twitter Card summaries, but they are disabled by

Twitter Cards enable you to show additional information in Tweets that
link to you content. Nikola supports [Twitter
Cards]( They are implemented to use
*Open Graph* tags whenever possible.

::: {.admonition}

To use Twitter Cards you need to opt-in on Twitter. To do so, please
visit <>

Images displayed come from the [previewimage]{.title-ref} meta tag.

You can specify the card type by using the [card]{.title-ref} parameter

To enable and configure your use of Twitter Cards, please modify the
corresponding lines in your ``:

``` {.sourceCode .python}
    'use_twitter_cards': True,  # enable Twitter Cards
    'card': 'summary',          # Card type, you can also use 'summary_large_image',
                                # see
    'site': '@website',         # twitter nick for the website
    'creator': '@username',     # Username for the content creator / author.

Custom Plugins

You can create your own plugins (see extending{.interpreted-text role="doc"}) and use them in your own site by putting them in a plugins/ folder. You can also put them in directories listed in the EXTRA_PLUGINS_DIRS configuration variable.

Getting Extra Plugins

If you want extra plugins, there is also the Plugins Index.

Similarly to themes, there is a nice, built-in command to manage them --- plugin:

$ nikola plugin -l

$ nikola plugin --install helloworld
[2013-10-12T16:51:56Z] NOTICE: install_plugin: Downloading:
[2013-10-12T16:51:58Z] NOTICE: install_plugin: Extracting: helloworld into plugins
[2013-10-12T16:51:58Z] NOTICE: install_plugin: This plugin has Python dependencies.
[2013-10-12T16:51:58Z] NOTICE: install_plugin: Installing dependencies with pip...
[2013-10-12T16:51:59Z] NOTICE: install_plugin: Dependency installation succeeded.
[2013-10-12T16:51:59Z] NOTICE: install_plugin: This plugin has a sample config file.
Contents of the file:

    # Should the Hello World plugin say “BYE” instead?
    BYE_WORLD = False

Then you also can uninstall your plugins:

$ nikola plugin --uninstall tags
[2014-04-15T08:59:24Z] WARNING: plugin: About to uninstall plugin: tags
[2014-04-15T08:59:24Z] WARNING: plugin: This will delete /home/ralsina/foo/plugins/tags
Are you sure? [y/n] y
[2014-04-15T08:59:26Z] WARNING: plugin: Removing /home/ralsina/foo/plugins/tags

And upgrade them:

$ nikola plugin --upgrade
[2014-04-15T09:00:18Z] WARNING: plugin: This is not very smart, it just reinstalls some plugins and hopes for the best
Will upgrade 1 plugins: graphviz
Upgrading graphviz
[2014-04-15T09:00:20Z] INFO: plugin: Downloading:
[2014-04-15T09:00:20Z] INFO: plugin: Extracting: graphviz into /home/ralsina/.nikola/plugins/
[2014-04-15T09:00:20Z] NOTICE: plugin: This plugin has third-party dependencies you need to install manually.
Contents of the requirements-nonpy.txt file:


You have to install those yourself or through a package manager.

You can also share plugins you created with the community! Visit the GitHub repository to find out more.

You can use the plugins in this repository without installing them into your site, by cloning the repository and adding the path of the plugins directory to the EXTRA_PLUGINS_DIRS list in your configuration.

Advanced Features


For pdb debugging in Nikola, you should use instead of the usual pdb call. By default, doit (and thus Nikola) redirects stdout and stderr. Thus, you must use the different call. (Alternatively, you could run with nikola build -v 2, which disables the redirections.)

Shell Tab Completion

Since Nikola is a command line tool, and this is the 21st century, it\'s handy to have smart tab-completion so that you don\'t have to type the full commands.

To enable this, you can use the nikola tabcompletion command like this, depending on your shell:

$ nikola tabcompletion --shell bash --hardcode-tasks > _nikola_bash
$ nikola tabcompletion --shell zsh --hardcode-tasks > _nikola_zsh

The --hardcode-tasks adds tasks to the completion and may need updating periodically.


Nikola is released under a MIT license which is a free software license. Some components shipped along with Nikola, or required by it are released under other licenses.

If you are not familiar with free software licensing: In general, you should be able to do pretty much anything you want, unless you modify Nikola. If you modify it, and share it with someone else, that someone else should get all your modifications under the same license you got it.

  1. The dump needs to be in 1.2 format. You can check by reading it, it should say xmlns:excerpt="" near the top of the file. If it says 1.1 instead of 1.2 you will have to update your WordPress before dumping.

    Other versions may or may not work.