<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog blog("Baptiste Wicht"); (Posts about Nikola)</title><link>https://baptiste-wicht.com/</link><description></description><atom:link href="https://baptiste-wicht.com/categories/nikola.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 15 Feb 2026 06:57:40 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Upgrade to Nikola 7</title><link>https://baptiste-wicht.com/posts/2015/11/upgrade-to-nikola-7.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;I've finally taken the time to upgrade the website to Nikola 7 (it is about time, I know...).&lt;/p&gt;
&lt;p&gt;The migration worked flawlessly, I simply had to update configuration to migrate deprecated and renamed tags and it worked really well. I also had to add a comma to the COMPILERS list because of the use of Python 3.3 now.&lt;/p&gt;
&lt;p&gt;As you may have seen, I haven't posted in a while. I had quite some work for my thesis as well as for the courses I give at my school and I started playing Path Of Exile with took quite a bit of my free time :) I'll try to give some updates on the project I'm working on to make this blog live again.&lt;/p&gt;</description><category>Nikola</category><category>Personal</category><category>The site</category><guid>https://baptiste-wicht.com/posts/2015/11/upgrade-to-nikola-7.html</guid><pubDate>Fri, 20 Nov 2015 09:56:32 GMT</pubDate></item><item><title>Related posts on a Nikola website</title><link>https://baptiste-wicht.com/posts/2014/04/related-posts-nikola-website.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;The one thing I missed in Nikola was the lack of &lt;strong&gt;Related Posts generation&lt;/strong&gt;. I solved this during &lt;a href="http://baptiste-wicht.com/posts/2014/03/migrated-from-wordpress-to-nikola.html"&gt;the migration from WordPress to Nikola&lt;/a&gt;, by using simple algorithms to generate related posts for each blog post and then display them in the form of a simple widget. &lt;/p&gt;
&lt;p&gt;For example, you can see the related posts of this post on the left, just under my Google+ badge. &lt;/p&gt;
&lt;p&gt;Here is the workflow that is used: 
 * A simple C++ tool generate a list of related posts in HTML for each posts
 * The generated HTML code is included in the MAKO template using Python&lt;/p&gt;
&lt;p&gt;In this article, I'll show how the related posts are generated and how to include them in your template.&lt;/p&gt;
&lt;h2&gt;Related Post Generation&lt;/h2&gt;
&lt;p&gt;It is important to note that it is necessary to cleanup the content of the files before using it: 
 * First, it is necessary to remove all HTML that may be present in the Markdown files. I remove only the HTML tags, not their content. For instance, in &lt;em&gt;&amp;lt;strong&amp;gt;test&amp;lt;/strong&amp;gt;&lt;/em&gt;, test would be counted, but not strong. The only exception to that, is that the content of preformatted parts (typically some or console output) is completely removed.
 * It is also necessary to cleanup Markdown, for instance, parentheses and square brackets are removed, but not their content. Same goes for Markdown syntax for bold, italics, ...
 * Finally, I also remove punctuation. &lt;/p&gt;
&lt;p&gt;My related posts algorithm is very simple. &lt;/p&gt;
&lt;p&gt;First, I compute the Term Frequency (TF) of each word in each post. The number of times a word is present in a document is represented by &lt;em&gt;tf(w,d)&lt;/em&gt;. I decided to give a bigger importance to words in the title and the tags, but that is just a matter of choice. &lt;/p&gt;
&lt;p&gt;After that, I compute the Inverse Document Frequency (IDF) of each word. This measure allows to filter words like: a, the, and, has, is, ... These words are not really representative of the content of a blog post. The formula for idf is very simple: &lt;em&gt;idf(w) = log(N / (1+ n(w)))&lt;/em&gt;. &lt;em&gt;n(w)&lt;/em&gt; is the number of posts where the word is present. It is a measure of rarity of a word on the complete posts set. &lt;/p&gt;
&lt;p&gt;Once we have the two values, we can easily compute the TF-IDF vectors of each blog post. The TF-IDF for a word is simply: &lt;em&gt;tf_idf(w,d) = tf(w, d) * idf(w)&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Finally, we can derive the matrix of Cosine similarities between the TF-IDF vectors. The idea of the algorithm is simple: each document is represented by a vector and then the distance between two vectors indicates how related two posts are. The formula for the Cosine similarity is also simple: &lt;em&gt;cs(d1, d2) = dot(d1, d2) / ||d1|| * || d2||&lt;/em&gt;. &lt;em&gt;d1&lt;/em&gt; and &lt;em&gt;d2&lt;/em&gt; are two TF-IDF vectors. Once the cosine similarities between each document is computed, we can just take the N most related documents as the "Related Posts" for each blog post. &lt;/p&gt;
&lt;p&gt;With this list, the C++ program simply generates an HTML file that will be included in each post by Nikola template. This process is &lt;strong&gt;very fast&lt;/strong&gt;. I have around 200 posts on this blog and the generation takes about 1 second. &lt;/p&gt;
&lt;h2&gt;Include in template&lt;/h2&gt;
&lt;p&gt;Once the HTML files are generate, they are included into the website by altering the template and adding their content directly into the web page. Here is the code I use in &lt;em&gt;base.tmpl&lt;/em&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="cp"&gt;%&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_link&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/stories/'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;div class="left-sidebar-widget"&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;        &amp;lt;h3&amp;gt;Related posts&amp;lt;/h3&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;        &amp;lt;div class="left-sidebar-widget-content"&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt;
                &lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;os&lt;/span&gt;
                &lt;span class="n"&gt;related_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;related_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;related_dir&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;source_link&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".related.html"&lt;/span&gt;

                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;related_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'r'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;related_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                        &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;IOError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;related_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Not generated"&lt;/span&gt;
            &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;            &lt;/span&gt;&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;related_text&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;
&lt;span class="x"&gt;        &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="x"&gt;    &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;%&lt;/span&gt;&lt;span class="k"&gt;endif&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You could also display it in &lt;em&gt;post.tmpl&lt;/em&gt; as a simple list. &lt;/p&gt;
&lt;p&gt;There is a limitation with this code: it only works if the source file has the same name than the slug, otherwise the file is not found. If someone has a solution to get the path to the source file and not the slug version, I'd be glad to have it ;)&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The code for the generator is available on the &lt;a href="https://github.com/wichtounet/wichtounet.github.io/tree/master/src/related"&gt;Github repository of my website&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;I wrote it in C++ because I don't like Python a lot and because I'm not good at it and it would have taken me a lot more time to include it in Nikola. If I have time and I'm motivated enough, I'll try to integrate that in Nikola. &lt;/p&gt;
&lt;p&gt;I hope that could be useful for some people. &lt;/p&gt;</description><category>Algorithm</category><category>C++</category><category>Nikola</category><category>Python</category><category>The site</category><guid>https://baptiste-wicht.com/posts/2014/04/related-posts-nikola-website.html</guid><pubDate>Sat, 05 Apr 2014 14:16:45 GMT</pubDate></item><item><title>Migrated from Wordpress to Nikola</title><link>https://baptiste-wicht.com/posts/2014/03/migrated-from-wordpress-to-nikola.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;As you're reading this post, the site has been migrated from WordPress to &lt;a href="http://www.getnikola.com/"&gt;Nikola&lt;/a&gt; and is now hosted on Github. Nikola is a static site generator. &lt;/p&gt;
&lt;h3&gt;Reasons of the migration&lt;/h3&gt;
&lt;p&gt;I had several reasons to migrate my website from WordPress to a static site generator: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I was getting tired of WordPress. It not a bad tool, but it is becoming heavier and heavier. I think that one of the biggest problems is that you need tons of plugins to make a fully-functional blog. I had more than 20 plugins. And each time you upgrade WordPress, you run into problems with the addons. In my opinion, while I understand why you need plugins for syntax highlighting for instance, you should not need any plugin for performances or security. Moreover, when you think of it a blog is not dynamic, I write less than a post a week and most bloggers write about once a day, in the computer science's sense, it is not dynamic at all. So why bother with a database ?&lt;/li&gt;
&lt;li&gt;I wanted to use my favourite tools for modifying my blog: the shell and vim. I don't think that wysiwyg editors are really adding any value to editing. I am faster writing posts in vim than I'm in a web editor. &lt;/li&gt;
&lt;li&gt;I wanted to be able to edit my website offline. With a static generator, as long as you have the files on your computer, you can edit your site and even browse it offline. You can then deploy it on the internet later when you are online. &lt;/li&gt;
&lt;li&gt;I wanted to host my blog at Github Pages, for fun! Moreover, I had some uptime issues with my host with quite some downtime in the last months. And it saves me some bucks each year, at least it was not a strong factor. &lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;The quest for a good static blog generator&lt;/h3&gt;
&lt;p&gt;It has been several months already since I started thinking about migrating my blog. I had quite a hard time to find a suitable blog generator. &lt;/p&gt;
&lt;p&gt;I needed something: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simple&lt;/li&gt;
&lt;li&gt;Completely usable in command line&lt;/li&gt;
&lt;li&gt;With a WordPress import feature&lt;/li&gt;
&lt;li&gt;Fast: I didn't wanted to spend a long time generating the website. &lt;/li&gt;
&lt;li&gt;Actively developed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problem is that there are tens of static site generator. I considered several of them. The most well known is Jekyll. It really looks fine, but I have to say that I HATE Ruby. I think it is an horrible language with an even more horrible environment. I cannot even have Ruby installed on my computer. So I didn't spend a long time considering Jekyll. I also considered Hyde, which is the evil brother of Jekyll, but I think that it was missing documentation to be completely usable for me. I also though of Pelican, but I was not convinced with it. &lt;/p&gt;
&lt;p&gt;I don't know how, but at first I didn't found about Nikola. It was only after some time that I came across Nikola by pure luck. Once I came accross Nikola, I directly was convinced by it. Nikola is written in Python and has a large set of features but still keeps the whole think very simple. Generation of the website is pretty fast. Even though I don't like Python very much, I'm able to stand its environment and if necessary I can hack around a bit. I also considered Hyde, which is the evil brother of Jekyll, but I think that it was missing documentation to be completely usable for me. I also though of Pelican, but I was not convinced with it. &lt;/p&gt;
&lt;p&gt;I don't know how, but at first I didn't found about Nikola. It was only after some time that I came across Nikola by pure luck. Once I found about Nikola, I directly was convinced by it. Nikola is written in Python and has a large set of features but still keeps the whole think very simple. Generation of the website is pretty fast. Even though I don't like Python very much, I'm able to stand its environment and if necessary I can hack around a bit. So I decided to try the complete migration. &lt;/p&gt;
&lt;h3&gt;The migration&lt;/h3&gt;
&lt;p&gt;Once I decided to migrate to Nikola, I directly started by importing my WordPress site into a Git repository. This process is quite simple, you just have to export and XML dump from WordPress and then import it into Nikola with the *import_wordpress" command. This already downloads the necessary images and resources and create posts and pages corresponding to your site. It also generates some redirections from the old URL scheme to the new one. &lt;/p&gt;
&lt;p&gt;However, there is still some manual work to be done. Here is what I had to do after I imported my WordPress site into Nikola: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As syntax highlighting was done by a plugin, I had to convert it to Markdown myself. This was quite easy, just a matter of &lt;em&gt;sed&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;I was not satisfied with the default templates so I enhanced it myself. As I'm a very poor web developer and even poorer web designer, it took me a long time, even if it is a simple one. &lt;/li&gt;
&lt;li&gt;I wanted to add some visibility to the comments, so I used Disqus API to create Most Popular and Recent Comments widgets. &lt;/li&gt;
&lt;li&gt;I had to create some redirections by myself for the tags and categories. This was again just a matter of simple shell commands. I filled a bug about it so it'll probably be fixed in the near future.&lt;/li&gt;
&lt;li&gt;I tried to improve the performances of the generated website, but I'm still gonna work on this later, the calls to Disqus and Google javascripts are the ones that takes the most of the load time. I think that a static site could be even faster. &lt;/li&gt;
&lt;li&gt;Finally, I really missed the options to have related posts generated for each posts, so I hacked a simple way to include them for each posts. The related posts are generated using a very simple algorithm. I'll soon write a post about how I have done this. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Except from these things, it hasn't been too hard to migrate to Nikola. &lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Until now I'm really satisfied with Nikola and I hope this will motivate me to write more blog posts in the coming months. I hope you'll find the website as enjoyable as before (or even more :) ). &lt;/p&gt;
&lt;p&gt;If you are interested, you can read the &lt;a href="https://baptiste-wicht.com/posts/2014/03/migrated-from-wordpress-to-nikola.wp"&gt;source of this blog post&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Even though I tried my best to avoid 404 or problems with the new site, I'm pretty sure there will be some issues in the following weeks. If you happen to found a dead link or some part of the website is not working for you, don't hesitate to comment this post and I'll my best to fix it. If you have suggestions on how to improve the site or have a question about the process of migrating a website from Wordpress to Nikola, I'd be glad to answer you. &lt;/p&gt;</description><category>Nikola</category><category>Personal</category><category>The site</category><category>WordPress</category><guid>https://baptiste-wicht.com/posts/2014/03/migrated-from-wordpress-to-nikola.html</guid><pubDate>Sun, 23 Mar 2014 21:23:21 GMT</pubDate></item></channel></rss>