Updates to my blog including shutting the comment section down

For almost 10 years, I have been using the Disqus comment management system to manage my posts’ comments. Last year, when I was moving to Germany, I have decided to hide the comment section by default. The main reason behind the idea was, since Disqus is considered a third-party and it is using cookies, and to prevent displaying the annoying pop-up informing visitors that “the website is using cookies”, I hide it until users really want to leave a comment (or viewing them). After near a year, I think that the comment section is not useful anymore; therefore, I decided to remove it completely this time.

People who blog these days are not looking for comments or impressions. They just write because they love to. I can vividly see that the amount of bloggers decreased significantly during the last 5-7 years and the main reason of that is social media. Most people prefer to just send their updates through series of tweets or Facebook posts. So, their social network get informed automatically. On the other hand, I think nearly all people who still blog are not doing it because they want to inform visitors or keep them up-to-date.

In addition to the comment section, I also removed the bootstrap CSS library. I have been using this to implement the theme. However, a few days back, I decided to implement the simplest grid system ever existed (as it was my main dependency to Bootstrap) and remove it completely.

After removing the Bootstrap, I can finally say that this blog is just pure HTML and around 200 lines of CSS. And, due to the fact that I don’t use any analytics or trackers (I removed Google Analytics about a year ago), there’s no Javascript is used as well!

Why?

As you may know, I am a big fan of science especially when it comes to physics and more specifically astrophysics. A few weeks back I was watching a video about science on YouTube and suddenly a video in the side column got my attention.

It was a video from Richard Feynman, the famous physicist, in which the interviewer asks him a very simple yet valid question about magnets. The question is about why something happens and Feynman answer is very interesting. I don’t want to spoil it so please take a moment and watch this ~7 minutes video:

My ultimate Neovim configuration for Python development

It’s about 5 years that I’m using Neovim as my daily text editor especially when it comes to software development. On the other hand, I do lots of Python programming during the last 4 years and so to develop more comfortably, I had to configure my text editor as well. In this post, I’m going to explain my daily setup for Python software development.

Tools

There are a few tools I use besides Neovim that help me a lot during my everyday development.

Terminal Emulator

Since I’m developing on macOS these days, my primary terminal of choice is iTerm2. I had also tried the macOS built-in terminal but I found that iTerm2 has better integration with Tmux so that I moved to it.

Shell

In term of shell, I moved to zsh (mainly through oh-my-zsh) about 5 years ago because I found it much better in compare to bash. OMZ community offer lots of useful plugins to choose from; but, for me these are my favorites:

plugins=(
    git
    docker
    docker-compose
    kubectl
    colored-man-pages
    git-flow
)

Tmux

Tmux plays a very important role in my daily development environment. I was using the neovim built-in terminal however I realized that nothing replaces Tmux. I usually split my main development window into two horizontal panes. The pane in the above for Neovim and the second pane which is located below that is for running tests and Git operations. I sometimes use the vim-fugitive plugin but in some cases, I believe it’s move convenient to use git in another window. Tmux panes

Neovim

If you’re a vim user, you are probably familiar with plugin managers. Vundle, Pathogen and Plugged are the three most popular ones. I was using Vundle for a long time, but recently I have moved to Plugged because I find it more customization about more easy to use. The plugins I use these days are:

" A fuzzy file finder
Plug 'kien/ctrlp.vim'
" Comment/Uncomment tool
Plug 'scrooloose/nerdcommenter'
" Switch to the begining and the end of a block by pressing %
Plug 'tmhedberg/matchit'
" A Tree-like side bar for better navigation
Plug 'scrooloose/nerdtree'
" A cool status bar
Plug 'vim-airline/vim-airline'
" Airline themes
Plug 'vim-airline/vim-airline-themes'
" Nord
Plug 'arcticicestudio/nord-vim'
" Better syntax-highlighting for filetypes in vim
Plug 'sheerun/vim-polyglot'
" Intellisense engine
Plug 'neoclide/coc.nvim', {'branch': 'release'}
" Git integration
Plug 'tpope/vim-fugitive'
" Auto-close braces and scopes
Plug 'jiangmiao/auto-pairs'

For python development, I was previously using jedi-vim alongside YouCompleteMe but after the presentation of Coc I completely hooked! Coc is a Nodejs extension host for Neovim which allows you to install npm based plugins (which is currently used in other text-editors such as VSCode) easily.

After installing Coc, I was able to install all the plugins I want to for my development environment very easily and just by using the CocInstall <package-name> command. Here is a list of all plugins I use:

  • coc-spell-checker: The general spell checker for neovim
  • coc-prettier: A very popular code formatter
  • coc-git: A git plugin to show which line is added/deleted and not committed
  • coc-pyright: The main Python plugin I use
  • coc-json: JSON file formatting plugin
  • coc-docker: Dockerfile and docker-compose formatters
  • coc-yaml: Yaml plugin for Kubernetes and terraform files

After installing your desired plugins it’s also a good idea to do a CocUpdate once in a while to keep your plugins up-to-date.

Then I set the following the shortcuts for the Coc for more ease of use:

" Code action on <leader>a
vmap <leader>a <Plug>(coc-codeaction-selected)<CR>
nmap <leader>a <Plug>(coc-codeaction-selected)<CR>

" Format action on <leader>f
vmap <leader>f  <Plug>(coc-format-selected)
nmap <leader>f  <Plug>(coc-format-selected)
" Goto definition
nmap <silent> gd <Plug>(coc-definition)
" Open definition in a split window
nmap <silent> gv :vsp<CR><Plug>(coc-definition)<C-W>L

Like VSCode, Coc also has a setting JSON file. For example, to formatOnSave or set a code formatter and linter, you can use that file. To open the setting file CocConfig command can be used. These are settings I use for Python development:

{
  "coc.preferences.formatOnSaveFiletypes": ["py", "yaml", "json"],
  "python.linting.flake8Enabled": true,
  "python.formatting.provider": "black"
}

Please also note that black and flake8 are external tools and need to be installed separately:

python3 -m pip install black flake8

There some other shortcuts which can be set to make your life easier as well. For example, I have set one to trigger NerdTree and showing hidden files:

map <C-n> :NERDTreeToggle<CR>
let NERDTreeShowHidden=1 " Show hidden files in NerdTree buffer.

Or for better split-view navigation:

" Split windows
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

Nord

Last but not least I use Nord theme almost everywhere. Nord has ports for almost everything. For example, for neovim you may add the following plugin:

Plug 'arcticicestudio/nord-vim'

And then add:

filetype plugin indent on
syntax on
colorscheme nord

I hope this post helped you setup your CLI based development environment as well :)

The move

Berlin. Photo taken from: https://strongcitiesnetwork.org/en/wp-content/uploads/sites/5/2017/11/Berlin-Nikolaiviertel-scaled.jpg There are some certain events that change people’s lives and all of us may experience one or some of them. For example, when one gets married, or when one becomes a parent. These events cause radical changes. You cannot be the same person after you become a father or mother. On the other hand, people want to grow. They take risks to become a better person. For example, one may take risk and start a new business. The business may fail, but at the same time it may make you grow!

Living in Iran is challenging especially for developers. During my 15 years of experience, I faced lots of restrictions. Most companies ar not allowed to provide their services to Iranians. On the other hand, Iranians can not trade with people in other countries because of banking restrictions. For example, buying a $5/month droplet from DigitalOcean, which is one of the most trivial things to do for developers, is a challenge for Iranians. Therefore, companies who are able to pay for these services are reselling them with twice (or even higher) the price. For instance, renewing a “.com” domain will cost you around $20 while the real price is just $10.

These were just some of the challenges Iranians are facing. But as a matter of fact, these are not my problem. My problem is uncertainty! You may be able buy a razor today, but you may not be able to find the razor blades after 6 month or so! You cannot plan you future because things change very rapidly and in a chaotic manner. People decide to buy a car so they start to save some money. They know they can buy their desired car in 6 months. But when the price increases everyday, one can’t plan in advance. This is what I call uncertainty.

That’s why we decided to move. We left our parents, siblings and friends to grow. To make a better future for ourselves and our children. We do it so we can gain access to resources other people in the world have. We may have to sacrifice things to be able to achieve something else. But we have done it.

It’s about a month that we have moved to Berlin. We were in a 10-day mandatory quarantine as we arrived but after 10 days we started to discover new things. One of the things that I lik about here is the German lifestyle. I like it that people pay attention to the environment and so on. Because of the COVID-19 we couldn’t discover most of attractions yey as amusement parks, cinemas, museum, concerts, etc are closed. Although we were are able to communicate comfortably in English but we’ve also started to learn German as well as some people tend to use German over English.

Moving to another country is difficult but I hope we get over this challenge as well.

Implementing GDPR in my blog

GDPR General Data Protection Regulation (GDPR) is the EU regulation to protect user data and privacy in Europe. A friend from Europe contacted a few days ago and told me that you don’t have cookie notice in your website and asked to do something about it.

My blog is powered by Jekyll which is a static site generator. It doesn’t (actually can’t) gather users’ data by itself. The only way to do so is by utilizing third-party JavaScripts. Except for one section, which is the comment section, I don’t use any third-party scripts. I don’t even have Google Analytics enabled on this blog. So to be able to truly implement the GDPR, I must only load the comment section when the user accepted the terms.

The approach

There were two approaches for implementing GDPR here:

  • Whenever a new user comes in, ask to allow cookies by showing a pop-up or something similar (The most common way).
  • Only show the cookie notice when the user is in a post page and wants to see/write a comment.

I believe the second approach is much better. Most of the times, users just want to read the blog post and leave. They don’t want to leave a comment. Therefore, I don’t even load the comment section at all! Instead, I show the following notice and when the user accepted the terms, I will load comments:

GDPR notice

Implementation

Disqus comment section is loaded into a <div> element using an inline javascript. So to implement this section I must first make sure the user accepted the cookie notice and then load the section. When the user click the approve button, I create a cookie. If the cookie doesn’t exist, I realize that the user has not approved yet. So I wrote two functions; one for getting the cookie value by name (getCookie(cname)), and the second is for setting the cookie value (setCookie(cname, value, exdays)).

function getCookie(cname) {
  var name = cname + '=';
  var decodedCookie = decodeURIComponent(document.cookie);
  var ca = decodedCookie.split(';');
  for (var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }

  // Return empty string if cookie with specified name not found.
  return '';
}

function setCookie(cname, cvalue, exdays) {
  var d = new Date();
  d.setTime(d.getTime() + exdays * 24 * 60 * 60 * 1000);
  var expires = 'expires=' + d.toUTCString();
  document.cookie = cname + '=' + cvalue + ';' + expires + ';path=/';
}

The first function getCookie check all website cookies to see if there’s any match with the name cname. If not, it returns an empty string. You may also want to return undefined instead but I chose to just return an empty string. In addition to these function I also have two divs. The one for loading the Diqus comments in and the second for the notice itself:

<div id="disqus_thread"></div>
<div id="cookie_notice" class="alert alert-info">
  The comment section uses cookies and third-party JavaScripts. To enable
  comments please click the approve button. For more information please checkout
  <a
    href="https://help.disqus.com/en/articles/1717103-disqus-privacy-policy"
    target="_blank"
    >Disqus privacy policy</a
  >
  <button id="approve_cookie" class="btn btn-sm btn-primary">Approve</button>
</div>

Then I have to handle the onClick event of the approve_cookie button to set the cookie when it’s clicked:

document.getElementById('approve_cookie').onclick = function () {
  setCookie('cookie-confirm-accepted', '1', 30);
  window.location.reload();
};

Finally I have to load the comment section only if the user accepted the terms; otherwise, the cookie notice div must be shown:

var cookie_container = document.getElementById('cookie_notice');
var disqus_config = function () {
  this.page.url = '[the page URL]';
  this.page.identifier = '[the page Identifier]';
};

(function () {
  cookie_container.style.display = 'block';
  if (getCookie('cookie-confirm-accepted') === '') {
    // Don't load the rest if the user cookie was empty
    return;
  }
  cookie_container.style.display = 'none';
  var d = document,
    s = d.createElement('script');

  s.src = 'https://[disqus username].disqus.com/embed.js';

  s.setAttribute('data-timestamp', +new Date());
  (d.head || d.body).appendChild(s);
})();

Please also note that the cookie we create has an expire date of 30 days (30 * 24 * 60 * 60 * 1000); so the notice will be shown again after that.

Beside GDPR, I also realized that my blog loads much faster since there is once less library to load. The only libraries I’m currently use are Bootstrap and PT Serif font from Google Fonts.

In Misc | 09 Feb 2021