Nikola Internals

Nikola Internals

When trying to guide so­meone in­to ad­ding a fea­ture in Ni­ko­la, it hit me that w­hile the way it’s struc­tu­red makes sense to me it is far from ob­vious.

So, this is a short do­cu­ment ex­plai­ning what each piece of Ni­ko­la does and ­how it all fits to­ge­ther.

Nikola is a Pile of Plugins

Most of Ni­ko­la is im­ple­men­ted as plu­gins using Yap­sy. You can ignore that they are plu­gins and just think of them as re­gu­lar py­thon ­mo­dules and pa­ckages with a fun­ny lit­tle .plu­gin file next to them.

So, 90% of the ti­me, what you want to do is ei­ther write a new plu­gin or ex­tend an exis­ting one.

There are se­ve­ral kinds of plu­gins, all im­ple­men­ting in­ter­faces de­fi­ned in ni­ko­la/­plu­gin_­ca­te­go­ries.­py and do­cu­men­ted in Ex­ten­ding Ni­ko­la

If your plu­gin has a de­pen­den­cy, please make sure it doesn’t make Ni­ko­la ­throw an ex­cep­tion when the de­pen­den­cy is mis­sing. Try to fail gra­ce­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

Ni­ko­la’s goal is si­mi­lar, deep at heart, to a Ma­ke­file. Take sour­ces, com­pile them in­to so­me­thing, in this case a web­site. Ins­tead of a Ma­ke­fi­le, Ni­ko­la uses doit

Doit has the concept of “tasks”. The 1 mi­nute sum­ma­ry of tasks is that they ha­ve:

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

So, what Ni­ko­la does, when you use the build com­mand, is to read the ­con­fi­gu­ra­tion conf.­py from the cur­rent fol­der, ins­tan­tia­te the Ni­ko­la class, and have it ge­ne­rate a whole list of tasks for doit ­to pro­cess. Then doit will de­cide which tasks need doing, and do them, in the right or­der.

The place where the tasks are ge­ne­ra­ted is in Ni­ko­la.­gen_­tasks, which col­lects tasks ­from all the plu­gins in­he­ri­ting Ba­se­Task, mas­sages them a bit, then passes them ­to doit.

So, if you want things to hap­pen on build you want to create a Task plu­gin, or ex­tend one of the exis­ting ones.

Posts and Stories

Ni­ko­la has a concept of posts and sto­ries. Both are more or less the same thing, ex­cept ­posts are ad­ded in­to RSS feeds and sto­ries are not. All of them are in a list cal­led “the ti­me­li­ne” for­med by ob­jects of class Post.

When you are crea­ting a task that needs the list of posts and/or sto­ries (for exam­ple, the RSS crea­tion plu­gin) on task exe­cu­tion ti­me, your plu­gin should call self.­site.scan_­posts() in gen_­tasks to en­sure the ti­me­line is crea­ted and avai­lable in self.­site.­ti­me­line. You should not mo­di­fy the ti­me­li­ne, be­cause it will cause consis­ten­cy is­sues.

Your plu­gin can use the ti­me­line to ge­ne­rate “s­tuff” (tech­ni­cal term). For exam­ple, ­Ni­ko­la comes with plu­gins that use the ti­me­line to create a web­site (sur­pri­sed?).

The work­flow in­clu­ded with ni­ko­la is as fol­lows (in­com­ple­te!):

  1. The post is as­si­gned a com­pi­ler ba­sed on its ex­ten­sion and the COM­PI­LERS op­tion.
  2. The com­pi­ler is ap­plied to the post da­ta and a “HTML frag­ment” is pro­du­ced. That ­frag­ment is sto­red in a cache (the posts plu­gin).
  3. The confi­gu­red theme has tem­plates (and a tem­plate en­gi­ne), which are ap­plied to the post’s HTML frag­ment and me­ta­da­ta (the pages plu­gin).
  4. The ori­gi­nal sources for the post are co­pied to some ac­ces­sible place (the sources plu­gin).
  5. If the post is tag­ged, some pages and RSS feeds for each tag are up­da­ted (the tags plu­gin).
  6. If the post is new, it’s in­clu­ded in the blog’s RSS feed (the rss plu­gin).
  7. The post is ad­ded in the right place in the in­dex pages for the blog (the in­dexes plu­gin).
  8. CSS/­JS/I­mages for the theme are put in the right places (the co­py_as­sets and bundles plu­gins).
  9. A File des­cri­bing the whole site is crea­ted (the si­te­map plu­gin).

You can add wha­te­ver you want to that list: just create a plu­gin for it.

You can al­so ex­pand Ni­ko­la’s ca­pa­bi­li­ties at se­ve­ral points:

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

And of cour­se, you can al­so re­place or ex­tend each of the exis­ting plu­gins.

Nikola Architecture