Nikola Internals

Nikola Internals

When try­ing to guide some­one in­to adding a fea­ture in Niko­la, it hit me that while the way it’s struc­tured makes sense to me it is far from ob­vi­ous.

So, this is a short doc­u­ment ex­plain­ing what each piece of Niko­la does and how it all fits to­geth­er.

Nikola is a Pile of Plugins

Most of Niko­la is im­ple­ment­ed as plug­ins us­ing Yap­sy. Y­ou can ig­nore that they are plug­ins and just think of them as reg­u­lar python ­mod­ules and pack­ages with a fun­ny lit­tle .plug­in file next to them.

So, 90% of the time, what you want to do is ei­ther write a new plug­in or ex­tend an ex­ist­ing one.

There are sev­er­al kinds of plu­g­in­s, all im­ple­ment­ing in­ter­faces de­fined in niko­la/­plug­in_­cat­e­gories.py and doc­u­ment­ed in Ex­tend­ing Niko­la

If your plug­in has a de­pen­den­cy, please make sure it does­n’t make Niko­la throw an ex­cep­tion when the de­pen­den­cy is miss­ing. Try to fail grace­ful­ly with an in­for­ma­tive mes­sage.

Commands are plugins
When you use nikola foo you are using the plugin command/foo. Those are used to extend Nikola’s command line. Their interface is defined in the Command class. They take options and arguments and do whatever you want, so go wild.
The build command is special
The build command triggers a whole lot of things, and is the core of Nikola because it’s the one that you use to build sites. So it deserves its own section.

The Build Command

Niko­la’s goal is sim­i­lar, deep at heart, to a Make­file. Take sources, com­pile them in­to some­thing, in this case a web­site. In­stead of a Make­file, Niko­la us­es doit

Doit has the con­cept of “tasks”. The 1 minute sum­ma­ry of tasks is that they have:

actions
What the task does. For example, convert a markdown document into HTML.
dependencies
If this file changes, then we need to redo the actions. If this configuration option changes, redo it, etc.
targets
Files that the action generates. No two actions can have the same targets.
basename:name
Each task is identified by either a name or a basename:name pair.

So, what Niko­la does, when you use the build com­mand, is to read the ­con­fig­u­ra­tion con­f.py from the cur­rent fold­er, in­stan­ti­ate the Niko­la class, and have it gen­er­ate a whole list of tasks for doit ­to process. Then doit will de­cide which tasks need do­ing, and do them, in­ the right or­der.

The place where the tasks are gen­er­at­ed is in Niko­la.­gen_­tasks, which col­lects tasks from all the plug­ins in­her­it­ing Base­Task, mas­sages them a bit, then pass­es them ­to doit.

So, if you want things to hap­pen on build you want to cre­ate a Task plug­in, or ex­tend one of the ex­ist­ing ones.

Posts and Stories

Niko­la has a con­cept of posts and sto­ries. Both are more or less the same thing, ex­cep­t ­posts are added in­to RSS feeds and sto­ries are not. All of them are in a list called “the time­line” formed by ob­jects of class Post.

When you are cre­at­ing a task that needs the list of posts and/or sto­ries (for ex­am­ple, the RSS cre­ation plug­in) on task ex­e­cu­tion time, your plug­in should call self­.site.s­can_­post­s() in gen_­tasks to en­sure the time­line is cre­at­ed and avail­able in self­.site.­time­line. You should not mod­i­fy the time­line, be­cause it will cause con­sis­ten­cy is­sues.

Your plug­in can use the time­line to gen­er­ate “stuff” (tech­ni­cal ter­m). For ex­am­ple, Niko­la comes with plug­ins that use the time­line to cre­ate a web­site (sur­prised?).

The work­flow in­clud­ed with niko­la is as fol­lows (in­com­plete!):

  1. The post is as­signed a com­pil­er based on its ex­ten­sion and the COM­PIL­ERS op­tion.
  2. The com­pil­er is ap­plied to the post da­ta and a “HTML frag­men­t” is pro­duced. That frag­ment is stored in a cache (the posts plug­in).
  3. The con­fig­ured theme has tem­plates (and a tem­plate en­gine), which are ap­plied to the post’s HTML frag­ment and meta­da­ta (the pages plug­in).
  4. The orig­i­nal sources for the post are copied to some ac­ces­si­ble place (the sources plug­in).
  5. If the post is tagged, some pages and RSS feeds for each tag are up­dat­ed (the tags plug­in).
  6. If the post is new, it’s in­clud­ed in the blog’s RSS feed (the rss plug­in).
  7. The post is added in the right place in the in­dex pages for the blog (the in­dex­es plug­in).
  8. CSS/JS/Im­ages for the theme are put in the right places (the copy­_as­sets and bun­dles plu­g­in­s).
  9. A File de­scrib­ing the whole site is cre­at­ed (the sitemap plug­in).

You can add what­ev­er you want to that list: just cre­ate a plug­in for it.

You can al­so ex­pand Niko­la’s ca­pa­bil­i­ties at sev­er­al points:

compilers
Nikola supports a variety of markups. If you want to add another one, you need to create a Compiler plugin.
templates
Nikola’s themes can use Jinja2 or Mako templates. If you prefer another template system, you have to create a TemplateSystem plugin.
themes
To change how the generated site looks, you can create custom themes.

And of course, you can al­so re­place or ex­tend each of the ex­ist­ing plug­ins.

Nikola Architecture

https://getnikola.com/images/architecture.thumbnail.png