Tuan Anh

container nerd. k8s || GTFO

Another attempt at regular blogging

I believe blogging help me learn better. In order to write about a subject, first I have to understand it throughly. Blogging is a way to documentating all your thought, your understanding into words.

Many people I talked with afraid of being wrong on the Internet. Don’t be. I do it all the time. I learnt a lot from the feedbacks.

If the feedback is right, you then learn something new, which is great. That’s the whole point, right!

If you’re wrong, please don’t get offended. A feedback could be wrong but it will also help you understand the subject better and get better at defending your view. Either way, it helps.

Actually, being wrong may actually speed up the learning process.

“The best way to get the right answer on the Internet is not to ask a question, it’s to post the wrong answer.”

Cunningham’s Law

You will be surprised at number of people can’t wait to prove you wrong.

duty calls

Paginated post plugin for jekyll

I was wondering if anyone has created one like this before and stumbled across this issue on octopress repo. imathis came up with this proposition for paginated post.

  • The primary page would be the standard post url.

  • Successive pages would be at post-url/2/index.html, etc.

  • The atom feed will still show the full un-broken post.

  • A unified post will live at post-url/all/index.html containing a print-friendly, un-broken version of the post.

  • Pagination at the bottom will like to each page followed by a link to post-url/all/.

  • Posts will have paginate: true in their YAML header to enable this feature.

  • Posts will be broken up by html comments like <!--page-->.

  • The un-broken post will add visual page divisions, probably an <hr>.

  • There will be a way to direct read-later services (like Instapaper) to the un-broken post page.

I don’t actually need this plugin as my posts are mostly short posts but I will take this as a fun exercise over this weekend or next. The plugin will be available on GitHub later.

Writing your first jekyll plugin

jekyll documentation is actually a very good source if you want to learn about writing a jekyll plugin. I highly recommend you to read that first. There are many examples at the end of the page as well.

Jekyll has a plugin system with hooks that allow you to create custom generated content specific to your site. You can run custom code for your site without having to modify the Jekyll source itself.

In general, plugins you make will fall into one of three categories:

  • Generators
  • Converters
  • Tags and liquid filters

We shall try with liquid filter first today, which is the easiest one IMO. In this tutorial, we will create a plugin that convert [x] and [] into emoji icon checkbox.

Filters are simply modules that export their methods to liquid. All methods will have to take at least one parameter which represents the input of the filter. The return value will be the output of the filter.

Create a file named Checked.rb in your _plugins folder with content as below.

module Jekyll
  module Checked
    def checked(text)
      text.sub(%r{\[x\]}i, '<span class="ballot_box_with_check"></span>').sub(%r{\[\]}i, '<span class="ballot_box"></span>')


We just created a module with a method that take a string as param and replace [x] and [] with a span tag with respective class.

We will then apply this filter on post content (or anything you want to apply this filter on).

{% content | checked %}

In your css file:

.ballot_box_with_check:before {
  content: "\2611\ ";

.ballot_box:before {
  content: "\2610\ ";

The result looks something like this

check jekyll plugin

And there you have it: your very first jekyll plugin. Be sure to check back for more jekyll tutorials :) .

How to use jekyll plugins with GitHub Pages

Very cool idea by @randymorris. Basically, actual source will now live in the source branch and generated content (_site folder) will be in master instead.

  1. Make changes in the source branch
  2. Build and test the site locally
  3. Commit changes to source branch
  4. git publish-website which consists of the following steps
git branch -D master
git checkout -b master
git filter-branch --subdirectory-filter _site/ -f
git checkout source
git push --all origin

This is actually similar to the approach: develope locally and rsync _site folder with your VPS/host public folder but works with GitHub Pages.

link bài gốc

Embedding Liquid code snippet with jekyll

If you want to share some Liquid code snippet or say some Django code, jekyll would try to process it as it looks like valid Liquid template and throw some weird errors.

The solution is to use raw tag. Again, I cannot use raw tag nested inside raw tag. Though, you would probably never have to do it, unless writing a blog post about something like this.

{% include analytics.html %}

Monthly/yearly post archive generator plugin for jekyll

Basically, this plugin will generate a archive based on your specified layout so that you can access it at url like


At first, I thought this is one of the default feature of jekyll but I was mistaken toto for jekyll. toto was another static site generator that I used before.

Anyway, this is what you are gonna get at the end.

jekyll archive plugin
1 - Example result of using jekyll archive plugin

I’m not the author of this plugin. I just modified it to suit my needs, adding stuff like: grouping post, generate yearly archive.

If you want to take a peak, head over to the plugin’s repo on GitHub.

Blogging with jekyll

I started using jekyll with Github Pages few years back but Github Pages didn’t allow plugins at the time and I do want to hack a bit around jekyll for my needs so I gradually move to self-hosting. As for static blog doesn’t require much resource, I opted for the lowest package on RamNode which goes for $15 a year (a bit over a buck a month for a 128MB RAM VPS). This is actually plenty for my needs.

Install jekyll

Install rvm or rbenv. If you already have one, skip this, then install jekyll

curl -L https://get.rvm.io | bash -s stable --ruby=2.0.0
gem install jekyll

Create your new blog and git init it.

jekyll new example.org
cd example.org
git init
git add .
git commit -m "Initial commit"
jekyll serve --watch


I create a script on my repo post-receive. Upon receive my push commit, the script will rebuild the site from source, output it to nginx public folder /usr/share/nginx/html/example.org and purge varnish cache afterword. Purging varnish cache is optional but I do change my CSS/JS occationally now and then so I put it there as well.

You can do this by following this tutorial on DigitalOcean - “How To Deploy Jekyll Blogs with Git”. It’s pretty easy to follow. Use your copy-paste-fu.

Note: If you’re using Ubuntu 14.04 or later, you will have to do to apt-get install nodejs as well. jekyll itself doesn’t depend on nodejs but execjs does.


I wrote a bunch of posts about jekyll as well. Check these out if they interest you.

Happy blogging. Don’t forget to share your cool jekyll hack on your new hippy blog.

BetterTube - A jekyll plugin for embedding YouTube videos

Sample syntax

{% youtube http://youtu.be/NiYCgVKioI4 %}

or even shorter

{% youtube NiYCgVKioI4 %}

Basically, this plugin will replace your youtube tag with a beautiful, responsive thumbnail of the video instead of loading the iframe and a bunch of other stuff along with that iframe, right on page load (pagespeed, remember?). On click, it will replace the image with the iframe for embedding video and play (autoplay=1). And did i mention it’s responsive too?

I will publish this plugin on Github as soon as I clean up the code.

The plugin is now available on Github.

Optimizing the hell out of your site for PageSpeed

Static assets bundling

I wrote a post about static assets combine on jekyll but the idea is similar to other framework. You can even do this on Wordpress via plugin called W3TC IIRC. As for your theme’s images, use CSS sprites to combine it to a single image. There are many tools for this purpose.

This step is critial because number of requests has a very high impact on page load. You would get a few points for PageSpeed already after this step.

Make use of Content Delivery Network (CDN)

CDN deploys your content across multiple, geographically dispersed servers, making your page loads faster from vistors’ perspective.

Also, try to load external library from a popular CDN. Chance your visitors already cache jQuery on Google CDN is pretty high. Why not take advantage of this?

CDN is cheap now. Even the free option CloudFlare is pretty good. Use it.


This one doesn’t take much time either. CloudFlare can also do it for you if you’re lazy.

Defer, async when possible

Defer and async all the scripts where possible. The rules are simple

  • Without defer or async, HTML parsing is paused when js code executes.

  • Defer will delay the script execution until HTML parsing is done.

  • Async won’t care when the script will be available. The script will be executed as soon as it’s ready. You may not want to use async if you have other scripts depend on that.

If you need to put external scripts (analytics, ads, etc..) on your site, try to find their async version. Most of the popular ads network provide async code snippet for your site.

Put JavaScript which are deferable in the bottom before </body in case your visitors’ browsers are not HTML5-compatible.

Optimize images

Yahoo Smush.it is a popular tool for this purpose. There’s a WordPress plugin to make it even easier to use. If you prefer an app for offline use, ImageOptim is good.

Use static site generator

jekyll is good. I have a very good experience with it. If you want a ready-to-use jekyll, take a look at Octopress. There are tons of other options as well. Take a pick.

Reverse proxy

If you’re already using a static site generator and nginx to serve it, I’m not sure if a reverse proxy would help. In my benchmark, varnish has roughly the same performance as nginx when serving static html. However, say you’re using a dynamic language like PHP with WordPress, varnish helps a lot. An old website of mine used to be able to handle 200,000 hit a day on a single $5 droplet on DigitalOcean where peak user online count was around 800, according to Google Analytics. Without varnish, the site was pretty much unresponsive.

I uses varnish to drop cookies on static assets as well as reverse proxy in front of nginx.

Google’s mod pagespeed

Pretty easy to install with apache, a bit more troublesome with nginx. I highly recommend you to install this. It makes your job a whole lot easier.


I did few of those tweaks and get 93/100 on Pagespeed and 99/100 on gtmetrix. Not bad for half an hour of your time huh. If i have more time, I will aim for something closer to 100 on Pagespeed.

There’s one suggestion on PageSpeed I don’t really understand . Until I figure it out, my score is probably stucked here.

None of the above-the-fold content on your page could be rendered without waiting for the following resources to load.

Static assets combine with jekyll

If you have several css files, each for different purpose, combining it into one would minimize HTTP requests and improve load times significantly. jekyll mades it very easy with include tag.

Here’s how you do it.

  • Move all the css files you want to include to _includes folder.

  • You create a new layout in _layouts folder called style.html and includes the needed css there.

layout: nil
/* syntax css, base css, or whatever you need to include */
{% include css/style.css %}
{% include css/syntax.css %}

This file is basically your base css file, including all the frequently used files.

  • Next, create your css file like below, include it in your head tag and you’re done. All your css files are now included in the layout style which you used as a base css for your main css.
layout: style

/* Your custom css goes here */

Alternatively, if your css file is rather small, you can embeded them right into the HTML file/layout like this. I’m not a fan of this as it would look a bit mess up, even just in the source code.

<title>Your page title</title>
    /* include it here. It will be replaced as your css file content */

Last step: check your PageSpeed score again and smile.