Until today, this blog has been powered by Wordpress and hosted by Bluehost.
That's a big change, and it actually took me many evenings, nights, and week-ends of hard work to make it happen.
So why did I go through all this? Well, both for you and for me, and here are the main reasons.
First, Wordpress is based on PHP. Taking apart the fact that it was a bit ridiculous to write a python blog on a PHP platform, I now have the possibility to code almost any feature I want by myself, all in python. On the contrary, in Wordpress, I had to rely on third party plugins, which I couldn't trust for speed nor security.
Second, Bluehost is just too slow. It is advertised as a good hosting solution everywhere on the internet, but I guess it's for historical reasons.
Finally, editing on Wordpress is a pain. You spend your time clicking around and fighting against a lousy, old-fashioned interface, it's laggy (certainly because of Bluehost), and I had no way to programmatically create or modify posts since I don't know PHP.
In this post, I will summarize what I have done, and point to the excellent documentation and blog posts I followed. That's not really a tutorial, but if you are interested in doing the same, you know that you can find help here.
If you're interested in any of the subjects described below, just drop me a comment at the bottom of this page, and I'll write a specific post about that.
Django is a fast and secure web framework based on python. If you know python, that's certainly the easiest way to build a dynamic website.
But django is not a content management system... If you want a web interface to add new pages, upload images, and write your posts, you need something more. There are various options on the market, such as django CMS or mezzanine. These are certainly excellent options, but I decided to go for the more recent wagtail, which features an excellent and fast content management interface, and offers more freedom in the definition of the document structure.
Here is how I got started with django and wagtail:
After these initial steps, I had a running blog.
But I was actually just getting started... What was coming next is covered in the following sections:
The style of a website is defined in cascading style sheets (CSS), which make it possible to define globally the properties of every element of the website. For example, you may use the CSS to choose a given font for all the text in the website, or to set the color of all titles.
Now, writing a full set of CSS for the whole website can be painful. Also, I'm not a professional web designer, and I know that I'm not able to come up with a custom style that most people will find acceptable. Finally, I wanted my website to be responsive, for quality display on computers, mobile phones, and tablets.
Fortunately, bootstrap is doing all of that for us!
With just a few additional lines in your html code, you're going to obtain the style of this blog.
I like it, so I didn't try to customize it further.
Now, if you're on a computer at the moment, try to reduce the width of your browser window and check the effect. This website is going to behave very well on a mobile phone as well.
Internationalization (i18n for i - 18 letters... - n) consists in both translation and localization. What is translation is obvious. Localization, on the other hand, consists in adapting the website to the needs of particular location. For example, in the US, people write 1 pm while in France, we typically write 13:00.
For this website, I just had to deal with translation.
The django documentation for translation is good, so you could just follow it.
The only tricky aspect is translating the tags, that you can see in the box on the right (or at the bottom if you use a mobile phone), and the language switcher at the top of this page.
In this blog, the tags are implemented with django-taggit. I literally spent days trying to translate these tags using bare django and wagtails, to no avail.
In the end I resorted to a simple solution:
Media files are the images and videos that are uploaded to the website through the content management system (here wagtail).
I could have chosen to host these files at my place on the computer that is running the web server.
But soon ( I hope ;-) ) there will be thousands of you guys hitting my server at the same time. And at this point, the media files will saturate my uplink.
So I decided to store these files on Amazon S3, which is a reliable, scalable, and cheap solution.
If you want to know how to do that, you can start by having a look at the official wagtail documentation for S3 media files, but clearly it's not enough, and it won't even work with the most recent Amazon S3 interface.
When you get blocked, check this ultimate guide.
Docker is a light containerization solution. If you have never used it, you can give it a try in my tutorial Data pipeline with Docker, InfluxDB, and Grafana.
For this website, I run two docker containers, arranged in a docker stack:
The postgreSQL server port is only available from the web server in the stack, and the web server port is hidden behind an nginx reverse proxy on another computer, that provides TLS encryption through a Let's Encrypt certificate.
That's a big subject for any scientific blog.
What I'm doing is to export the jupyter notebooks into html using the basic template option. Then, I import the resulting html file as a django template.
The CSS classes for the Facebook and Twitter share buttons are from bootstrap-social (I've just downloaded this CSS file). The SVG images for the logos in the buttons have been taken from Simple Icons.
For the comments, I first tried the most popular option, which is Disqus. But Disqus is slow, unreliable, and it is tracking you. So I went for Commento. With Comento, you pay what you want, there is no tracking, and two lines are enough to set it up.
You can test it at the bottom of this page!
Before getting started with this endeavor, my biggest worry was to import all the existing posts from Wordpress into Wagtail.
But that was actually quite easy.
In Wordpress, I used the export function to get an xml file containing all published posts as an RSS feed.
I parsed this feed with the feedparser and Beautiful Soup (bs4) python packages, and directly created the wagtail posts in my python script. After importation, I run another script to update all internal links between the various posts, again with Beautiful Soup.
That was only a short summary of the steps I've taken to provide you with this new version of the blog.
I hope you'll like it!
And again, if you want a detailed tutorial about any aspect mentioned above, just tell me in the comments.
Please let me know what you think in the comments! I’ll try and answer all questions.
And if you liked this article, you can subscribe to my newsletter to be notified of new posts (no more than one mail per week I promise.)
You can join my newsletter to learn more about machine learning and data: