Creating a Nikola coding blog

This is a comprehensive walk-through of how to set up a static blog site with Nikola, specifically for creating a Jupyter Notebook code blog. Although there are other websites that show you how to do this, I found they weren't particularly comprehensive and it took me quite some time to wrap my head around Nikola and how to use it effectively.

Most of the other websites are for older versions of Nikola, and the walk-through below is for Nikola version 8.01 and I am deploying my website to GitHub pages, although you can use other repos like GitLab or BitBucket.


  • To get the best results for a presentable webpage/blog, accept the fact that your blog will need to be written with a combination of the below:

    • Markdown: Use this for basic blog posts

    • reStructured Text: Use this for more advanced or longer blog posts that need additional details such as a contents page.

    • html with Bootstrap: Use this for customized pages that require special and graphics (i.e., carousels).

  • Feel free to each out to the folks on Nikola-Discuss Google Groups or access the #nikola IRC channel on Freenode_. To `/join #nikola channel, you'll need to register yourself on Freenode.

  • html is your best bet if you want to make specific customizations to your webpage.

  • The best form of flattery is imitation! If you see a Nikola website that you like, clone the src branch of that webpage and have a look at the inner workings of the website to see how to adapt it to your needs. It may not be able to compile properly due to the different versions of Nikola, but at least you can see how they've structured their website.

1 Installing Nikola

In your github folder, create a folder for your blog.

$ mkdir nikola

Go into your github\nikola folder.

$ cd github \ nikola

Create a conda environmet for nikola.

$ conda create -n nikola

Activate your nikola environment.

$ source activate nikola

Install packages needed by nikola installation.

$ conda install pip setuptools wheel pyphen pybtex

Upgrade pip.

$ pip install --upgrade pip

Install nikola by using pip. Don't install nikola using conda as the version on pip is newer.

$ pip install --upgrade "Nikola[extras]"

2 Creating a Nikola demo site

In your github folder, run the nikola command with a subfolder name where your blog contents are stored. In the below example blog2 is the subfolder name.

$ nikola init --demo blog2

Answer all the questions required to set up the site.

  • Site title: <SITE_TITLE>.

  • Site author: <AUTHOR-NAME>.

  • Site e-mail: <AUTHOR-EMAIL>

  • Site description: <DESCRIPTION>

  • Enable pretty URLs: 'Y'

  • Languages to use : List all languages you want for your website.

  • Timezone : America/New_York

  • Comment system: 'disqus'

  • Comment system site identifier: You can find this in your Disqus profile page.

3 Contents of a Nikola website (i.e., blog2)

To understand how Nikola works, its good to have an understanding of the directories that are required by the Nikola website. All the contents of blog2 are synced to the src branch of your Github repo

├── cache
├── files
├── galleries
├── images
├── listings
├── output
├── pages
├── plugins
├── posts
├── __pycache__
├── templates
└── themes

Cache folder storing generated files. You can ignore this


All files stored in this directory will be copied into the root folder of your webpage (i.e., output)


Store galleries of images here such as images of your holidays, products, etc. Nikola has a galleries.tmpl that will render a gallery of images nicely for you.


Images that your website uses can be stored here.


Code files (e.g., *.py) that you want to allow readers to access are stored here. Typically these are just code instead of *.ipynb which can be used as walk-throughs of your code.


This is the root folder of your webpage. All files here are accessed and viewed by the web browser. Contents of this folder are synced to the master branch of your Github repo.


This is where all the written content for your webpages are stored. Typically files stored here are your landing page (i.e., index.html), about me page (i.e., about-me.html), and a contact me page (i.e., contact-me.html). Pages stored in this location are not likely to change much over time.


This is where all additional plugins that you have installed are stored. See Installing plugins for more details.


This is where the written content for your blog is stored. Typically the numbe r of pages in the posts folder will keep growing as you add more entries in your blog.


This is where additional templates for your blog are stored. Templates here will override the default templates that Nikola comes with


This is where the theme information for your blog is stored. It is particularly important if you are creating your own theme or if youre installing other themes from Bootswatch in here.

4 Writing a new post or page

You can create a new post or page with the below commands. The default file that is created is the first line in the POSTS or PAGES tuple in The PAGE/POST is saved in the output folder as shown in POSTS or PAGES tuple in See Preparing nikola for use with Jupyter notebooks for more details and as specified, reStructured text files are generated by default for new posts and new pages.

$ nikola new_post
$ nikola new_page

To write a new post or page in other formats than the default (i.e., markdown, ipynb, rst, or html) append the file type to new_post -f command as shown below.

$ nikola new_post -f md
$ nikola new_post -f rst
$ nikola new_page -f ipynb

When you use the nikola new_post command, it automatically creates the required metadata to publish each filetype successfully. More help for the nikola new_post function as below:

$ 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. (see also: `nikola new_page`)  (config: is_page)
  -t ARG, --title=ARG       Title for the post.  (config: title)
  -a ARG, --author=ARG      Author of the post.  (config: author)
  --tags=ARG                Comma-separated tags for the post.  (config: tags)
  -1                        Create the post with embedded metadata (single file format)  (config: onefile)
  -2                        Create the post with separate metadata (two file format)  (config: twofile)
  -e                        Open the post (and meta file, if any) in $EDITOR after creation.  (config: edit)
  -f ARG, --format=ARG      Markup format for the post (use --available-formats for list)  (config: content_format)
  -F, --available-formats   List all available input formats  (config: available-formats)
  -s                        Schedule the post based on recurrence rule  (config: schedule)
  -i ARG, --import=ARG      Import an existing file instead of creating a placeholder  (config: import)

5 Preparing nikola for use with Jupyter notebooks

For IPython notebooks to be published, you'll need to add Metadata into the files. In Jupyter Notebook (not Jupyter Lab, as editing metadata in Jupyter Lab is not available at the time of this post), select Edit in the Menubar, and select Edit Notebook Metadata. The below are the minimum metadata required for the ipynb file to be successfully published by Nikola.

"nikola": {
   "date": "2018-12-23",
   "slug": "backtest-portfolio-optimization",
   "title": "Backtesting portfolio optimization strategies"

The meta data that I include in my ipynb is shown in my cheatsheet. There are other metadata that can be added depending on your use case.

Add the *.ipynb in the POSTS and PAGES of (see line 6 and 13 below).

    ("posts/*.rst", "blog", "post.tmpl"),
    ("posts/*.md", "blog", "post.tmpl"),
    ("posts/*.txt", "blog", "page.tmpl"),
    ("posts/*.html", "posts", "post.tmpl"),
    ("posts/*.ipynb", "blog", "post.tmpl"),
    ("pages/*.rst", "pages", "page.tmpl"),
    ("pages/*.md", "pages", "page.tmpl"),
    ("pages/*.txt", "pages", "page.tmpl"),
    ("pages/*.html", "pages", "page.tmpl"),
    ("pages/*.ipynb", "pages", "page.tmpl")

6 Preparing nikola for use with Markdown files

Edit the to have the below markdown extensions. The markdown.extensions.meta is required for the nikola build command to the meta data for the date in the markdown file.


All your markdown files need the following meta data for Nikola to publish them successfully.

Title: Useful utilities for coding
Date: 2018-12-1
Slug: useful-coding-cmds
Tags: git, pelican, conda,
Categories: Utilities

7 Creating a website first, blog second!

I had quite a bit of trouble understanding how to set it up, thus I hope this will help explain it better than the Nikola website. I wanted a webpage that was a site first, and then blog posts under different categories.

If you create your own landing page, it needs ot be named index.html and located in the root folder of your webpage (i.e., in output) for it to be the first page that is viewed by the browser. However, the default settings in are such that Nikola will generate an index.html in the root folder of your webpage that is a list of the blog entries. The default has the following entry:


Since INDEX_PATH is empty, the index.html will be produced in the root folder of the webpage. We can either disable to generation of index.html altogether (which I would discourage) or you could tell Nikola to generate index.html but place it in another folder such as POSTS. This way, if you want to have a link for readers to access all the blog pages on your site, you can point them here.

INDEX_PATH ="posts"

8 Pages vs Posts

Nikola has two categories for entries into your website, that is POSTS and PAGES.


These are your blog posts and these will grow over time as you add more blog entries onto your webpage. POSTS are added to feeds, indexes, tag lists and archives.


These are generally static pages that may be built when you design your website. It is not generally expected that the number of PAGES will grow substantially whereas POSTS will.

The tuple shown below for POSTS and PAGES in is in the format of (source file type, output folder, template file).

    ("posts/*.html", "posts", "post.tmpl"),
    ("posts/*.ipynb", "posts", "post.tmpl"),
    ("posts/*.md", "posts", "post.tmpl"),
    ("posts/*.rst", "posts", "post.tmpl"),
    ("pages/*.html", "", "page.tmpl"),
    ("pages/*.ipynb", "pages", "page.tmpl"),
    ("pages/*.md", "pages", "page.tmpl"),
    ("pages/*.rst", "pages", "page.tmpl"),

Files in the posts directory that are html, ipynb, md, rst, and txt file types will be rendered using the post.tmpl template and output into the blog folder. Files in the pages directory that are ipynb,`rst`,`txt`, and md are rendered using page.tmpl and output into the pages folder.

The only file type that I do not want to be output into the pages directory are html files (see line 8 above). This is because if I placed "pages" as an output folder, than the index.html that I have written as a landing page would appear in the outputpages folder that is not the root directory of the static website generated by Nikola. I want all html files to be generated directly into the output folder that is the root directory of the static website generated by Nikola.

When Nikola renders a html file, it will also add other Nikola elements such as the menu bar. Thus, using html is useful when you are applying bespoke designs to a webpage that cannot be performed in Markdown or reStructured Text.


If you place your created index.html file in the output folder, it will not render with elements such as the menubar. Therefore, create a html file using nikola new_page -f html so the html file with metadata will be generated. As per the settings ("pages/*.html","","page.tmpl"), all html files in pages will be rendered by Nikola and placed in the root folder (i.e., output).

For example in PAGES, I have the following bespoke pages:

9 Using different themes

There are a whole range of Nikola themes available. Themes require installation and selecting the theme to use in Themes are installed in the themes directory of your Nikola folder.To install a theme use the following command:

nikola theme -i <THEME_NAME>

You will then need to ensure that has the following



Some themes (e.g., zen) require additional customization (i.e., "Suggested Configuration) of the, thus read the instructions for installing the theme carefully.

10 Using subthemes

Nikola includes the bootblog4 and bootstrap4 themes by default. bootblog4 is best for blogs and bootstrap4 is best for a webpage. I am using bootstrap4, that has different color configurations (known as subthemes in Nikola) available on bootswatch and hackerthemes. I am using the Cerulean theme from bootswatch. IMHO, themes from bootswatch are nicer than hackerthemes

nikola subtheme -s <SUBTHEME NAME>

The default main theme is always bootstrap4. If you want to use bootblog4 with a different subtheme use the following command

nikola subtheme -s <SUBTHEME NAME> -p bootblog4

If you are using a different subtheme with bootswatch or bootblog, you will need to set the theme to custom in

THEME = "custom"

You will find that in the themes/custom folder, using the subtheme command just downloads css stylesheets. Thus you can adjust these css stylesheets to get your own color configuration for our website if you wish.

11 Customizing the navigation bar

The below is a shortened example of how I customized my Menubar. You can see how Tags and Contact are configured to be direct links on the menu bar, and how Coding Blog and About are configured to have submenus with Trading, Python, All Posts, etc.

                ("/categories/cat_trading/", "Trading"),
                ("/categories/cat_python/", "Python"),
                ("/archive.html/", "Archived Posts"),
                ("/posts/", "All Posts"),
            "Coding Blog"
                ("/about-me/", "About me"),
                ("/pages/academic-publication/", "Publications"),
        ("/categories/index.html", "Tags"),
        ("/contact/", "Contact"),

12 Enabling Files and Listings

I have enabled Files and Listings in The contents of the files folder in Nikola will be copied into the root folder of the website (output) without modification. The Files folder can contain any scripts, files, pdfs, etc. that viewers can access or download. For example, I have the full-text pdfs of some of my publications in this folder.

The contents of the listings folder usually contains code or script that you would like users to download. For example, I have Python modules that I have written for viewers to download and use.

FILES_FOLDERS = {'files': ''}
LISTINGS_FOLDERS = {'listings': 'listings'}

13 Date formatting

I agree that blog posts need a date stamp, but a time stamp?! I also want blogs to indicate how long ago they were written (e.g., 2 months ago) rather than the date. The following settings are used in

DATE_FORMAT = 'yyyy-MMM-dd'

14 Categories vs Tags

Nikola provides posts and pages to be categorized using categories and tags. Typically, a posts can only belong in one category, but it can have multiple tags. My page has categories such as machine-learning, Python, natural language processing, etc. To enable multiple categories, the is configured as follows:

CATEGORY_PATH = "categories"
CATEGORIES_INDEX_PATH = "categories.html"

15 Customizing category landing pages

From your main landing page (i.e., index.html) you can customize the landing pages of each category in to have titles and descriptions.

For CATEGORY_TITLES, we have a dict where the keys are the reference names of the categories (i.e., "machine-learning", "nlp") and the values are the titles of the category ("Machine learning", "Natural Language Processing").

       "machine-learning": "Machine learning",
       "finance-economics": "Finance & Economics",
       "python" : "Python",
       "trading" : "Trading",

For CATEGORY_DESCRIPTIONS, we have a dict where the keys are the reference names of the categories (i.e., "machine-learning", "nlp") and the values are the descriptive text in html. Since it is html, you can have descriptive text and Java script (i.e., Subscribe here or Contact me links) if you choose. Below, I have a variable for MAIL_CHIMP and will provide more instructions in Mailchimp (Email subscription service).

       "trading": '''
        <p><h5>Democratizing the automated trading process!<h5></p>
        <p>This is a work in progress to find and contribute to an open source project for automated trading for retail investors.</p>
        ''' + '''
        ''' + MAIL_CHIMP + '''

       "python": '''
        <p><h5>The  canonical, "Python is a great first language", elicited, "Python is a great last language!"<h5><p>
        <p>I remember my first encounter with Python was in 2004 while my cousin was asking me for programming help, and I disregarded Python (to my regret!) as a toy language. I told him that he should focus on a real language like C, C++, or Java.  I humbly bite back my tongue and now realize the power of the open source community with Python.</p>  <p>I believe Python has really democratized programming is the best general purpose language out there! I cover interesting functionality or avant-garde new packages in Python.</p>
        ''' + '''
        ''' + EXCUSE_POST + '''

17 Showing teasers instead of the full post

The index.tmpl will generate a list of posts associated to the tag/category/year/author. This index can either be the (i) entire post (ii) post with just the teasers. To just show a teaser of the post, set as follows:


In Markdown or html or ipynb, select the end of your teasers with:

<!-- TEASER_END -->

In reStructuredText, select the end of your teasers with:


If you are using teasers, the default is a Read more... link to access the full post. To make it more informative, you can have statements such as XX minute read... in as shown below.

INDEX_READ_MORE_LINK = '<p class="more"><a href="{link}">{reading_time} minute read…</a></p>'
FEED_READ_MORE_LINK = '<p><a href="{link}">{read_more}…</a> ({min_remaining_read})</p>'

18 Showing your favourite icon

Pick an icon that you want to show up next to your webpage and store it in "/images/website/" of your Nikola folder. Edit the file as follows:

    ("icon", "/images/website/piggy-bank.png", "152x152"),

19 Deploying the website onto GitHub pages

You will need to have a GitHub account, and enable GitHub pages to deploy your webpage to your GitHub page (i.e.,

By using the nikola github_deploy command, this will create a src branch that will contain your contents (i.e., *.pynb, *.rst), and a master branch that will contain your html output pages that are viewed by the browser.

$ nikola github_deploy

Initialize github in your source directory (i.e., github/blog)

$ git init .
$ git remote add origin<USER_NAME>/<USER_NAME>

The should have the following settings.


Create a .gitignore file with the following entries as a minimum. You may use to generate a suitable set of .gitignore entries for your platform by typing in the relevant tags (e.g., linux,`nikola`,jupyternotebooks`).


20 Archives

Nikola has many options for how you would display your archive of posts. I've kept it pretty simple on my end.

# Create per-month archives instead of per-year
# Create one large archive instead of per-year
# Create year, month, and day archives each with a (long) list of posts
# If monthly archives or full archives are created, adds also one archive per day
# Create previous, up, next navigation links for archives
ARCHIVE_PATH = "archive"
ARCHIVE_FILENAME = "archive.html"

21 Images vs Galleries


Nikola has a nice template that renders a gallery of products or pictures you have on your webpage. There are several options you an set for the size of the gallery's thumbnails, images, names, and how it is sorted as shown below.

GALLERY_FOLDERS = {"galleries": "galleries"}
# More gallery options:
# If set to False, it will sort by filename instead. Defaults to True

Images are where I would place pictures that support my website. These would be pictures related to my blog posts or website icons or pictures that support my pages (e.g., About me).

IMAGE_FOLDERS = {'images': 'images'}
IMAGE_THUMBNAIL_FORMAT = '{name}.thumbnail{ext}'

22 Code blocks

As mentioned earlier, Nikola is great for a coding blog! We can also change what the code color scheme since it is based on Pygments. I am using monokai but you can see a gallery of available color styles in the Pygments gallery


23 License

Always good to add some sort of license for any information you have on your website!

<a rel="license" href="">
<img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"

25 Rendering math equations

I have enabled KaTeX because its prettier with the $...$ syntax as thats more similar to LaTeX.

delimiters: [
    {left: "$$", right: "$$", display: true},
    {left: "\\\\[", right: "\\\\]", display: true},
    {left: "\\\\begin{equation*}", right: "\\\\end{equation*}", display: true},
    {left: "$", right: "$", display: false},
    {left: "\\\\(", right: "\\\\)", display: false}

26 Showing & copying sources code for posts & pages?

If you would like to enable viewers to be able to show the link of the source of your posts, or copy the source this is easily done. I have disabled these settings for now.


27 Disabling ATOM/RSS feeds

Does anyone actually use ATOM/RSS feeds? I'm a little mixed about this setting, and am disabling it for the time being. Mainly because I want to remove the RSS Feeds link that comes up on all my category landing pages.


28 Implementing external web utilities

28.2 Disqus (Comments system)

To have a comments system available on your Nikola website, I recommend Disqus. Disqus is easy to setup and works well. Sign up for an account and Add Disqus to site. Follow the instructions and your COMMENT_SYSTEM_ID for Disqus is given by the Website Name that can be found on the Configure Disqus for your site.


Some people have concerns about the fact that Disqus owns the copyright to your comments, but I'm not bothered.

28.3 Mailchimp (Email subscription service)

Mailchimp allows you to run e-mail campaigns and contact subscribers when you have new content on your site. See Getting Started with Mailchimp for more detailed instructions.

When you are at the Customize your Signup Form step, Mailchimp will provide the html code similar to below and you need to use YOUR MAILCHIMP IDENTIFIER so that any subscriptions on your webpage will be linked to your Mailchimp account.

<!-- Begin Mailchimp Signup Form -->
        <div id="mc_embed_signup">
        <form action="<YOUR MAILCHIMP IDENTIFIER>;id=8e8f2aee39" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
            <div id="mc_embed_signup_scroll">
                <h3><label for="mce-EMAIL">Subscribe for updates</label></h3>
                <div class="col-sm-4">
                    <div class="input-group">
                        <input type="text" value="" style="display: inline;" name="EMAIL" class="form-control" id="mce-EMAIL" placeholder="Enter your email">
                     <span class="input-group-addon">
                        <button type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="btn btn-primary active">Subscribe</button>
                <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
                <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_ed1badab91e4777111fd1a645_8e8f2aee39" tabindex="-1" value="">
<!--End mc_embed_signup-->

28.4 Addthis (Social media sharing)

Using Addthis allows new icons to pop up on your page so that readers can share via a variety of social media platforms. When you sign up and configure what your social media icons look like, you can select Get the Code to obtain the html snippet that looks like the below with your website's unique identifier.

<!-- Go to to customize your tools -->
<script type="text/javascript" src="<YOUR ADDTHIS IDENTIFIER>"></script>

28.5 FontAwesome (Fonts & Icons)

I use several icons from FontAwesome on my main landing page. The link to the FontAwesome stylesheeds needed to be added into the pages HEAD tag. Once this is added, you can access all the icons and cool functionality you get with FontAwesome like stacking, rotation, animation, and more.

<!-- Font Awesome -->
<link rel="stylesheet" href=""
    integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">

28.6 Adding Google Analytics & Google AdSense

Google Analytics & Google AdSense can be added to the bottom of <body> to function.

BODY_END = """
<!-- Global Site Tag (gtag.js) - Google Analytics -->
<script async src=""></script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

<!-- Google AdSense -->
<script async src="//"></script>
  (adsbygoogle = window.adsbygoogle || []).push({
    google_ad_client: "<YOUR GOOGLE ADSENSE IDENTIFIER>",
    enable_page_level_ads: true

29 Installing plugins

Plugins allow additional functionality for your Nikola website.See Plugins for Nikola for the full list.

To install plugins, use the following command:

nikola plugin -i <PLUGIN_NAME>

To remove plugins, use the following command:

nikola plugin -r <PLUGIN_NAME>

Some interesting plugins that I think are interesting are:

  • medium. Publish your Nikola posts on Medium.

  • similarity. Find posts that are similar to the one being read. Requires install of Natural Language Processing packages such as gensim.

  • static_tag_cloud. Create a nice tag cloud.

  • publication_list. Create a list of publications in reStructured text from a BibTex file.

  • contentful. Interface for using a web UI to edit posts and pages.

I have only used publication_list that I needed to make several edits to the code and can be found in Publications.

30 Theme & Template customization

I'm pretty happy with themes available with Nikola (or too lazy to build my own!). However, there are certain tweaks I'd like to make to the webpage and the best way to do this is to customize the templates.

To create a new theme, we can use the following command which will create a new folder in themes called pythonicfinance which is using the mako templating engine and whose parent theme is`bootstrap4`. We don't necessarily want to create a theme from scratch, so we base it off the bootstrap4 theme (or whatever theme you want) and make the adjustments that we want.

$ nikola theme --new=pythonicfinance --engine=mako --parent=bootstrap4

We can also copy over any templates from the parent theme that we need to make adjusments to by using the following command

$ nikola theme --copy-template=base.tmpl

If you want to examine all the components of the parent theme (i.e., bootstrap4 in my case), the following command will give you the path to the parent theme for you to explore.

$ nikola theme -g bootstrap4

The full list of templates is shown below:

├── authors.tmpl
├── base_helper.tmpl
├── base.tmpl
├── gallery.tmpl
├── index_helper.tmpl
├── listing.tmpl
├── pagination_helper.tmpl
├── post.tmpl
├── tags.tmpl
└── ui_helper.tmpl

In my theme, I wanted to make the nav bar sticky to the top, so that when readers scroll downwards, they can still access the menu bar. To do so, I updated the base.tmpl file as shown below with the command sticky-top.

<nav class="navbar navbar-expand-md sticky-top mb-4


Comments powered by Disqus