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.

Its 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.

Keep in mind that "static" doesn't mean boring. You can have animations, slides
or whatever fancy CSS3/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.

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:

Security

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.

Obsolescence

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) page views from a phone using
static sites.

Lock-in

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.

You will want to do things like "link from one post to another" or "link to an image gallery",
etc. Sure, you can just figure out the URLs for each thing and use that. Or you can use
Nikola's special link URLs. Those are done using the syntax link://kind/name and
a full list of the included ones is here (BTW, I linked
to that using link://slug/path-handlers)

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, Jupyter (IPython) Notebooks, HTML as input,
can also use Pandoc for conversion, and has support for BBCode, CreoleWiki, txt2tags, Textile
and more via plugins — for more details, read the input format documentation.
You can learn reStructuredText syntax with the reST quickstart.

Please note that Nikola does not support encodings other than UTF-8. Make sure
to convert your input files to that encoding to avoid issues. It will prevent
bugs, and Nikola will write UTF-8 output anyway.

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)

You can edit these files with your favorite text editor, and once you are happy
with the contents, generate the pages using nikola build.

The post page is generated by default using the post.tmpl template, which you can use
to customize the output. You can also customize paths and the template filename
itself — see How does Nikola decide where posts should go?

Slug of the post. Used as the last component of the page URL. We recommend
and default to using a restricted character set (a-z0-9-_) because
other symbols may cause issues in URLs. (required)

date

Date of the post, defaults to now. Multiple date formats are accepted.
Adding a timezone is recommended. (required for posts)

tags

Comma-separated tags of the post. Some tags have special meaning, including
draft, private, mathjax

category

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

guid

String used as GUID in RSS feeds and as ID in Atom feeds instead of the
permalink.

link

Link to original source for content. May be displayed by some themes.

description

Description of the post. Used in <meta> tags for SEO.

type

Type of the post. See Post Types for details. 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)

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).

hyphenate

Set "True" if you want this document to be hyphenated even if you have
hyphenation disabled by default.

nocomments

Set to "True" to disable comments. Example:

password

The post will be encrypted and invisible until the reader enters the password.
Also, the post's source code 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!

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.

.. previewimage: /images/looks_great_on_facebook.png

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).

section

Section for the post (instead of inferring from output path; requires
POSTS_SECTION_FROM_META setting)

template

Change the template used to render this page/post specific page. That
template needs to either be part of the theme, or be placed in a
templates/ folder inside your site.

.. template: story.tmpl

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:

Metadata can be in different formats.
Current Nikola versions experimentally supports other metadata formats that make it more compatible with
other static site generators. The currently supported metadata formats are:

reST-style comments (.. name: value — default format)

Two-file format (reST-style comments or 7-line)

Jupyter Notebook metadata

YAML, between --- (Jekyll, Hugo)

TOML, between +++ (Hugo)

reST docinfo (Pelican)

Markdown metadata extension (Pelican)

HTML meta tags (Pelican)

You can add arbitrary meta fields in any format.

When you create new posts, by default the metadata will be created as reST style comments.
If you prefer a different format, you can set the METADATA_FORMAT to one of these values:

Jupyter posts can store meta information inside .ipynb files by using the nikola key inside notebook metadata. It can be edited by using Edit → Edit Notebook Metadata in Jupyter. Note that values are currently only strings. Sample metadata (Jupyter-specific information omitted):

{"nikola":{"title":"How to make money","slug":"how-to-make-money","date":"2012-09-15 19:52:05 UTC"}}

For HTML source files, metadata will be extracted from meta tags, and the title from the title tag.
Following Pelican's behaviour, tags can be put in a "tags" meta tag or in a "keywords" meta tag. Example:

<html><head><title>My super title</title><metaname="tags"content="thats, awesome"/><metaname="date"content="2012-07-09 22:28"/><metaname="modified"content="2012-07-10 20:14"/><metaname="category"content="yeah"/><metaname="authors"content="Conan Doyle"/><metaname="summary"content="Short version for index and feeds"/></head><body> This is the content of my super blog post.
</body></html>

If you import posts from other engines, those may not work with Nikola out of the box due to differing names. However, you can create a mapping to convert meta field names from those formats into what Nikola expects.

If you are writing a multilingual site, you can also create a per-language
post file (for example: how-to-make-money.es.txt 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
some_file.de.rst. This is because the TRANSLATIONS_PATTERN variable is by
default set to:

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

Note

Considered languages

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

In case you translate your posts, you might also want to adjust various
other settings so that the generated URLs match the translation. You can
find most places in conf.py by searching for (translatable). For example,
you might want to localize /categories/ (search for TAG_PATH), /pages/
and /posts/ (search for POSTS and PAGES, or see the next section), or
how to adjust the URLs for subsequent pages for indexes (search for
INDEXES_PRETTY_PAGE_URL).

Nikola supports multiple languages for a post (we have almost 50 translations!). If you wish to
add support for more languages, check out the Transifex page for Nikola

The place where the post will be placed by new_post (the first one that
matches the given format) and the final post destination (the first one that
matches a given file) is based on the POSTS and PAGES configuration
options. The exact mechanism is explained above the config options in the
conf.py file, and also reproduced below:

# POSTS and PAGES contains (wildcard, destination, template) tuples.## The wildcard is used to generate a list of post source files# (whatever/thing.rst, for example).## That fragment could have an associated metadata file (whatever/thing.meta),# and optionally translated files (example for Spanish, with code "es"):# whatever/thing.es.rst and whatever/thing.es.meta## 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/thing.html.es)## 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 page might also be placed in /destination/pagename/index.html# if PRETTY_URLS are enabled.## The difference between POSTS and PAGES is that POSTS are added# to feeds, indexes, tag lists and archives and are considered part# of a blog, while PAGES are just independent HTML pages.## Finally, note that destination can be translated, i.e. you can# specify a different translation folder per language. Example:# PAGES = (# ("pages/*.rst", {"en": "pages", "de": "seiten"}, "story.tmpl"),# ("pages/*.md", {"en": "pages", "de": "seiten"}, "story.tmpl"),# )POSTS=(("posts/*.rst","posts","post.tmpl"),("posts/*.txt","posts","post.tmpl"),("posts/*.html","posts","post.tmpl"),)PAGES=(("pages/*.rst","pages","story.tmpl"),("pages/*.txt","pages","story.tmpl"),("pages/*.html","pages","story.tmpl"),)

Note

POSTS and PAGES are not flat!

Even if the syntax may suggest you can't, you can create any directory structure you want
inside posts/ or pages/ and it will be reflected in the output. For example,
posts/foo/bar.txt would produce output/posts/foo/bar.html, assuming the slug is also bar.

If you have PRETTY_URLS enabled, that would be output/posts/foo/bar/index.html.

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 conf.py) 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 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 can also provide a directory name, in which case Nikola
will append the file name for you (generated from title).

The -d,--date-path option automates creation of year/month/day or
similar directory structures. It can be enabled on a per-post basis, or you can
use it for every post if you set NEW_POST_DATE_PATH = True in conf.py.

# Use date-based path when creating posts?# Can be enabled on a per-post basis with `nikola new_post -d`.# NEW_POST_DATE_PATH = False# What format to use when creating posts with date paths?# Default is '%Y/%m/%d', other possibilities include '%Y' or '%Y/%m'.# NEW_POST_DATE_PATH_FORMAT = '%Y/%m/%d'

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:

.. TEASER_END

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 behavior with your conf.py: INDEX_TEASERS defines whether index
page should display the whole contents or only teasers. FEED_TEASERS
works the same way for your Atom and 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

You can override the default value for TEASER_END in conf.py — for
example, the following example will work for .. more, and will be
compatible with both WordPress and Nikola posts:

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. This will not work if
lazily include nikola build in your DEPLOY_COMMANDS.

Also if a post has a date in the future, it will not be shown in indexes until
you rebuild after that date. This behavior 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.

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.

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.
Or if you are scared of this format, many calendaring applications (eg. Google
Calendar) offer iCal exports, so you can copy-paste the repeat rule from a
generated iCal (.ics) file (which is a human-readable text file).

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.

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:

Indexes are put in the INDEX_PATH directory, which defaults to an empty
string (site root). The “main” index is index.html, and all the further
indexes are index-*.html, respectively.

By default, 10 posts are displayed on an index page. This can be changed with
INDEX_DISPLAY_POST_COUNT. Indexes can show full posts or just the teasers,
as controlled by the INDEX_TEASERS setting (defaults to False).

Titles of the pages can be controlled by using INDEXES_TITLES,
INDEXES_PAGES and INDEXES_PAGES_MAIN settings.

Categories and tags use simple lists by default that show only titles and
dates; however, you can switch them to full indexes by using
CATEGORY_PAGES_ARE_INDEXES and TAG_PAGES_ARE_INDEXES, respectively.

Something similar happens with authors. To use full indexes in authors, set
AUTHOR_PAGES_ARE_INDEXES to True.

Nikola uses static indexes by default. This means that index-1.html has
the oldest posts, and the newest posts past the first 10 are in
index-N.html, where N is the highest number. Only the page with the
highest number and the main page (index-N.html and index.html) are
rebuilt (the others remain unchanged). The page that appears when you click
Older posts on the index page, index-N.html, might contain less than 10
posts if there are not enough posts to fill up all pages.

This can be disabled by setting INDEXES_STATIC to False. In that mode,
index-1.html contains all the newest posts past the first 10 and will
always contain 10 posts (unless you have less than 20). The last page,
index-N.html, contains the oldest posts, and might contain less than 10
posts. This is how many blog engines and CMSes behave. Note that this will
lead to rebuilding all index pages, which might be a problem for larger blogs
(with a lot of index pages).

Tags are the smallest and most basic of the taxonomy items. A post can have multiple tags, specified using the tags metadata entry (comma-separated). You should provide many tags to help your readers, and perhaps search engines, find content on your site.

Please note that tags are case-sensitive and that you cannot have two tags that differ only in case/punctuation (eg. using nikola in one post and Nikola in another will lead to a crash):

ERROR: Nikola: You have tags that are too similar: Nikola and nikola
ERROR: Nikola: Tag Nikola is used in: posts/second-post.rst
ERROR: Nikola: Tag nikola is used in: posts/1.rst

Nikola uses some tags to mark a post as “special” — those are draft, private, mathjax (for math support).

The next unit for organizing your content are categories. A post can have only one category, specified with the category meta tag. Those are deprecated and replaced by sections. They are displayed alongside tags. You can have categories and tags with the same name (categories’ RSS and HTML files are prefixed with cat_ by default).

Sections are the newest feature for taxonomy, and are not supported in themes by default. There are two ways to assign a section to a post:

through the directory structure (first directory is the section name, eg. /code/my-project/ is in the code category) — your POSTS should have those directories as the second element, eg.

POSTS=(('posts/code/*.rst','code','posts'),)

through the section meta field (requires POSTS_SECTION_FROM_META setting; recommended especially for existing sites which should not change the directory hierarchy)

Sections are meant to be used to organize different parts of your blog, parts that are about different topics. Unlike tags, which you should have tens (hundreds?) of, you should ideally have less than 10 sections (though it depends on what your blog needs; there is no hard limit).

With sections, you can also use some custom styling — if you install husl, you can use post.section_color() from within templates to get a distinct color for the section of a post, which you can then use in some inline CSS for the section name.

In order to use input formats other than reStructuredText, you need some extra
setup.

Make sure you have the compiler for the input format you want. Some
input formats are supported out-of-the-box, but others must be installed from
the Plugins repository. You may also need some extra dependencies. You
will get helpful errors if you try to build when missing something.

You must ensure the compiler and your desired input file extension is included
in the COMPILERS dict and does not conflict with any other format. This
is extremely important for the pandoc compiler.

Finally, you must configure the POSTS and PAGES tuples. Follow the
instructions and the format set by pre-existing entries. Make sure to use
the same extension as is set in COMPILERS and configure the outputs
properly.

To use Pandoc, you must uncomment the entry in COMPILERS and set the
extensions list to your desired extensions while also removing them from their
original compilers. The input format is inferred from the extension by Pandoc.

Using Pandoc for reStructuredText, Markdown and other input formats that have a
standalone Nikola plugin is not recommended as it disables plugins and
extensions that are usually provided by Nikola.

The first word is always the name of the shortcode. Parameters follow the name. Depending upon how the shortcode is defined, the parameters may be named, positional or both. The format for named parameters models that of HTML with the format name="value".

Some shortcodes use or require closing shortcodes. Like HTML, the opening and closing shortcodes match (name only), the closing being prepended with a slash.

Example of a paired shortcode (note that we don't have a highlight shortcode yet ;-):

{{% highlight python %}} A bunch of code here {{% /highlight %}}

Note

Shortcodes and reStructuredText

In reStructuredText shortcodes may fail because docutils turns URL into links and everything breaks.
For some shortcodes there are alternative docutils directives (example, you can use the media
directive instead of the media shortcode.

If you put a template in shortcodes/ called mycode.tmpl then Nikola
will create a shortcode called mycode you can use. Any options you pass to
the shortcode will be available as variables for that template. Non-keyword
options will be passed in a tuple variable named _args.

The post in which the shortcode is being used is available as the post
variable, so you can access the title as post.title, and data loaded
via the data field in the metadata using post.data(key).

If you use the shortcode as paired, then the contents between the paired tags
will be available in the data variable. If you want to access the Nikola
object, it will be available as site. Use with care :-)

In that case, the template engine used will be your theme's and the arguments you pass,
as well as the global context from your conf.py, are available to the template you
are creating.

You can use anything defined in your confguration's GLOBAL_CONTEXT as
variables in your shortcode template, with a caveat: Because of an unfortunate
implementation detail (a name conflict), data is called global_data
when used in a shortcode.

If you have some template code that you want to appear in both a template and
shortcode, you can put the shared code in a separate template and import it in both
places. Shortcodes can import any template inside templates/ and themes,
and call any macros defined in those.

For example, if you define a macro foo(x, y) in
templates/shared_sc.tmpl, you can include shared_foo.tmpl in
templates/special_post.tmpl and shortcodes/foo.tmpl and then call the
${shared_foo.foo(x, y)} macro.

There is a GLOBAL_CONTEXT field in your conf.py where you can
put things you want to make available to your templates.

It will also contain things you put in a data/ directory within your
site. You can use JSON, YAML or TOML files (with the appropriate file
extensions: json/js, yaml/yml, toml/tml) that decode to Python dictionaries.
For example, if you create data/foo.json containing this:

{"bar":"baz"}

Then your templates can use things like ${data['foo']['bar']} and
it will be replaced by "baz".

Individual posts can also have a data file. Those are specified using the
data meta field (path relative to conf.py, can be different in
different post languages). Those are accessible as eg.
${post.data['bar']} in templates. Template-based shortcodes are a
good idea in this case.

Data files can be useful for eg. auto-generated sites, where users provide
JSON/YAML/TOML files and Nikola generates a large page with data from all data
files. (This is especially useful with some automatic rebuild feature, like
those documented in Deployment)

Data files are also available as global_data, to avoid name conflicts in
shortcodes. (global_data works everywhere.)

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

# 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 conf.py 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 conf.py you get with Nikola should be fairly complete, and is quite
commented.

You surely want to edit these options:

# Data about this siteBLOG_AUTHOR="Your Name"# (translatable)BLOG_TITLE="Demo Site"# (translatable)SITE_URL="https://getnikola.com/"BLOG_EMAIL="[email protected]"BLOG_DESCRIPTION="This is a demo site for Nikola."# (translatable)

Some options are marked 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

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.conf.py,
you have to execute nikola build --conf=configurations/test.conf.py.

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 and creating themes

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:

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

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.)

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 highlighted when active.

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

Footer

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.

BODY_END

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.

SOCIAL_BUTTONS_CODE

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 for more details.

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).

Important

Don't put any files manually in output/. Ever. Really.
Maybe someday Nikola will just wipe output/ (when you run nikola check -f--clean-files) 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'

If you prefer to have a custom appearance for your site, and modifying CSS
files and settings (see Customizing Your Site for details) is not enough,
you can create your own theme. See the Theming Nikola and
creating-a-theme for more details. You can put them in a themes/
folder and set THEME to the directory name. You can also put them in
directories listed in the EXTRA_THEMES_DIRS configuration variable.

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 http://bootswatch.com:

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.

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.

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.

In order to use this feature, you need to configure a few things first. Make
sure you have nikola and git installed on your PATH.

GITHUB_DEPLOY_BRANCH is the branch where Nikola-generated HTML files
will be deployed. It should be gh-pages for project pages and
master for user pages (user.github.io).

GITHUB_SOURCE_BRANCH is the branch where your Nikola site source will be
deployed. We recommend and default to src.

GITHUB_REMOTE_NAME is the remote to which changes are pushed.

GITHUB_COMMIT_SOURCE controls whether or not the source branch is
automatically committed to and pushed. We recommend setting it to
True, unless you are automating builds with Travis CI.

Create a .gitignore file. We recommend adding at least the following entries:

cache
.doit.db
__pycache__
output

If you set GITHUB_COMMIT_SOURCE to False, you must switch to your source
branch and commit to it. Otherwise, this is done for you.

Run nikola github_deploy. This will build the site, commit the output
folder to your deploy branch, and push to GitHub. Your website should be up
and running within a few minutes.

If you want to use a custom domain, create your CNAME file in
files/CNAME on the source branch. Nikola will copy it to the
output directory. To add a custom commit message, use the -m option,
followed by your message.

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.

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, or on images with links in post, you will
see a bigger image, thanks to the excellent colorbox. If don’t want this behavior, add an
.islink class to your image or link. (The behavior is caused by
<a class="image-reference"> if you need to use it outside of galleries and reST
thumbnails.)

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 conf.py 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"}# More gallery options:THUMBNAIL_SIZE=180MAX_IMAGE_SIZE=1280USE_FILENAME_AS_TITLE=TrueEXTRA_IMAGE_EXTENSIONS=[]# If set to False, it will sort by filename instead. Defaults to TrueGALLERY_SORT_BY_DATE=True# Folders containing images to be used in normal posts or pages.# IMAGE_FOLDERS is a dictionary of the form {"source": "destination"},# where "source" is the folder containing the images to be published, and# "destination" is the folder under OUTPUT_PATH containing the images copied# to the site. Thumbnail images will be created there as well.IMAGE_FOLDERS={'images':'images'}# Images will be scaled down according to IMAGE_THUMBNAIL_SIZE and MAX_IMAGE_SIZE# options, but will have to be referenced manually to be visible on the site# (the thumbnail has ``.thumbnail`` added before the file extension by default,# but a different naming template can be configured with IMAGE_THUMBNAIL_FORMAT).IMAGE_THUMBNAIL_SIZE=400IMAGE_THUMBNAIL_FORMAT='{name}.thumbnail{ext}'

If you add a reST 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.

Your images contain a certain amount of extra data besides the image itself,
called the EXIF metadata.
It contains information about the camera you used to take the picture, when it was taken,
and maybe even the location where it was taken.

This is both useful, because you can use it in some apps to locate all the pictures taken
in a certain place, or with a certain camera, but also, since the pictures Nikola
publishes are visible to anyone on the Internet, a privacy risk worth considering
(Imagine if you post pictures taken at home with GPS info, you are publishing your
home address!)

Nikola has some support for managing it, so let's go through a few scenarios to
see which one you prefer.

Do this if you really know what you are doing. EXIF data comes separated in a few IFD blocks.
The most common ones are:

0th

Information about the image itself

Exif

Information about the camera and the image

1st

Information about embedded thumbnails (usually nothing)

thumbnail

An embedded thumbnail, in JPEG format (usually nothing)

GPS

Geolocation information about the image

Interop

Not too interesting at this point.

Each IFD in turn contains a number of tags. For example, 0th contains a ImageWidth tag.
You can tell Nikola exactly which IFDs to keep, and within each IFD, which tags to keep,
using the EXIF_WHITELIST option.

Additionally, you can provide a custom list of XPath expressions which should be used for finding headers ({hx} is replaced by headers h1 through h6).
This is required if you use a custom theme that does not use "e-contententry-content" as a class for post and page contents.

Prevent duplicated IDs in HTML output. An incrementing counter is added to
offending IDs. If used alongside add_header_permalinks, it will fix
those links (it must run after that filter)

IDs are numbered from the bottom up, which is useful for indexes (updates
appear at the top). There are exceptions, which may be configured using
DEDUPLICATE_IDS_TOP_CLASSES — if any of those classes appears sin the
document, the IDs are rewritten top-down, which is useful for posts/pages
(updates appear at the bottom).

Note that in rare cases, permalinks might not always be permanent in case
of edits.

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 share!

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.

Nikola uses MathJax by default. If you want to use KaTeX (faster and prettier,
but may not support every feature yet), set USE_KATEX = True in
conf.py.

To use mathematics in a post, you must add the mathjax tag, no matter
which renderer you are using. (Exception: posts that are Jupyter Notebooks are
automatically marked as math)

By default, Nikola will accept \​(...\​) for inline math; \​[...\​] and
$​$...$​$ for display math. If you want to use the old $...$ syntax as well
(which may conflict with running text!), you need to use special config for
your renderer:

Nikola supports the standard reStructuredText include directive, but with a
catch: filenames are relative to Nikola site root (directory with conf.py)
instead of the post location (eg. posts/ directory)!

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 sourcecode:

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 foo.py
inside one of these folders:

..listing:: foo.py python

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

The stand-alone listings/ pages also support Jupyter notebooks, if they are
supported site-wide.

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

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
output/formatted-code.

Note

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
end-line.

To include an image placed in the images folder (or other folders defined in IMAGE_FOLDERS), use the
thumbnail directive, like this:

..thumbnail:: /images/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 image
directive are supported (except target). If a body element is provided, the
thumbnail will mimic the behavior of the
figure
directive instead:

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 here

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.

Filter posts to show only posts having at least one of the tags.
Defaults to None.

require_all_tags:flag

Change tag filter behaviour to show only posts that have all specified tags.
Defaults to False.

categories:string [, string...]

Filter posts to show only posts having one of the categories.
Defaults to None.

sections:string [, string...]

Filter posts to show only posts having one of the sections.
Defaults to None.

slugs:string [, string...]

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

post_type (or type) :string

Show only posts, pages or all.
Replaces all. Defaults to posts.

all:flag

(deprecated, use post_type instead)
Shows all posts and pages in the post list. Defaults to show only posts.

lang:string

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

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.

The list may fail to update in some cases, please run nikola build -a with
the appropriate path if this happens.

We recommend using pages with dates in the past (1970-01-01) to avoid
dependency issues.

If you are using this as a shortcode, flags (reverse, all) are meant to be used
with a True argument, eg. all=True.

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 places

Will try to add redirects that send the old post URLs to the new ones

Will give you a URL map so you know where each old post was

This is also useful for DISQUS thread migration, or server-based 301
redirects!

Allows you to export your comments with each post

Exports information on attachments per post

There are different methods to transfer the content of your posts:

You can convert them to HTML with the WordPress page compiler plugin
for Nikola. This will format the posts including supported shortcodes
the same way as WordPress does. Use the --transform-to-html option
to convert your posts to HTML.

If you use this option, you do not need to install the plugin
permanently. You can ask Nikola to install the plugin into the subdirectory
plugins of the current working directory by specifying
the --install-wordpress-compiler option.

You can leave the posts the way they are and use the WordPress page
compiler plugin to render them when building your new blog. This also
allows you to create new posts using the WordPress syntax, or to manually
add more shortcode plugins later. Use the --use-wordpress-compiler
option to not touch your posts.

If you want to use this option, you have to install the plugin permanently.
You can ask Nikola to install the plugin into your new site by specifying
the --install-wordpress-compiler option.

You can let Nikola convert your posts to Markdown. This is not error
free, because WordPress uses some unholy mix of HTML and strange things.
This is the default option and requires no plugins.

You will find your old posts in new_site/posts/post-title.html in the first case,
new_site/posts/post-title.wp in the second case or new_site/posts/post-title.md
in the last case if you need to edit or fix any of them.

Please note that the page compiler currently only supports the [code] shortcode,
but other shortcodes can be supported via plugins.

Also note that the WordPress page compiler is licensed under GPL v2 since
it uses code from WordPress itself, while Nikola is licensed under the more
liberal MIT license.

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 we are happy to get requests
about it.

The dump needs to be in 1.2 format. You can check by reading it, it should say
xmlns:excerpt="http://wordpress.org/export/1.2/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.

You can specify the card type by using the card parameter in TWITTER_CARD.

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

TWITTER_CARD={'use_twitter_cards':True,# enable Twitter Cards'card':'summary',# Card type, you can also use 'summary_large_image',# see https://dev.twitter.com/cards/types'site':'@website',# twitter nick for the website'creator':'@username',# Username for the content creator / author.}

You can create your own plugins (see Extending Nikola) 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.

$ nikola plugin --upgrade
[2014-04-15T09:00:18Z] WARNING: plugin: This is not very smart, it just reinstalls some plugins and hopes for the bestWill upgrade 1 plugins: graphvizUpgrading graphviz[2014-04-15T09:00:20Z] INFO: plugin: Downloading: https://plugins.getnikola.com/v7/graphviz.zip[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: Graphviz http://www.graphviz.org/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.

For pdb debugging in Nikola, you should use doit.tools.set_trace() 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.)

To show more logging messages, as well as full tracebacks, you need to set an
environment variable: NIKOLA_DEBUG=1

Nikola is released under the 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, here is a brief
explanation (this is NOT legal advice): In general, you can do pretty much
anything you want — including modifying Nikola, using and redistributing the
original version or the your modified version. However, if you redistribute
Nikola to someone else, either a modified version or the original version, the
full copyright notice and license text must be included in your distribution.
Nikola is provided “as is”, and the Nikola contributors are not liable for any
damage caused by the software. Read the full license text for details.