Sorry but here's a new post about this blog. I've already talked about my choice of Jekyll as the engine for this blog.
Don't worry, I'm still very happy with it!
But we're not in the 20th century anymore and even if I don't need 99% of the features delivered by Wordpress, some are important to me.
I like the external links of my site to open a new tab/window (with the HTML target="_blank" attribute).
Since I didn't want to dig into Jekyll's rendering process, I chose to add the HTML attribute to all external links with some JavaScript:
var domain_root = document.location.protocol+'//'+document.location.host;
var all_links = $('a').each(function(index,element){
if(element.href.substr(0,domain_root.length) !== domain_root)
{
element.target = '_blank';
}
});
Yes I use jQuery and yes some of you will scream but I don't care, most of your CPU's cores are idle right now so I decided to put them to work a bit.
In modern browsers, it shouldn't slow down your browsing experience at all.
I will tweet 10 times more than I'll post here (at least and not counting RTs). So I wanted my Twitter feed included in this blog.
My first reflex was to try out Twitter's official JavaScript widget but let's be honest it's really ugly! And customize it is a pain in the a**.
So after searching a bit, I chose Tweet!. A lot more options, a dedicated CSS and I host it so I can fiddle a bit with it. I used Twitter's official icons and CSS sprites though.
For those, just go to this blog entry. It contains everything you need to build an RSS feed (I used feedburner to track you though :p ), the Categories page and do Search Engine Optimization (sitemap, keywords, etc.). Great stuff for everyone who wants to use/switch to Jekyll.
As you can see, I'm using Disqus. Not much more to add.
I'm using Bootstrap, the CSS toolbox from the Twitter team. Really easy for a style-impaired guy as myself. Works great on iOS too.
Finally, I get to the point where I discuss the second item of this entry's title: Node. The unofficial name of this beast is Node.js and for those who lived underground for the past year, it's server-side JavaScript on top of an event loop or as Ryan Dahl puts it: "evented I/O for V8 JavaScript".
There are a lot of resources available on the interwebs if you're interested in Node. I suggest you take a look at Ryan Dahl's talk and read this tutorial.
So, search. How do you add search to a static website?
First reflex: Google. Tried it, didn't work, too complicated and they even ask for money. No thanks.
Second idea: any plugin available for Jekyll? Yes but (there's always a "but", I know you saw it coming) it uses indextank API which a freemium service. No thanks.
Third idea: I can do it myself! But to stay consistent, let's not use PHP, Ruby or some usual server side language.
Let's populate the backlog:
Let's map this to Node and the existing setup:
How does it work?
There is first an indexing script and then the server part that delivers search results.
The indexing script parses a striped-down list of the posts generated by Jekyll and populate the SQLite DB. It is ran at build time. It seems simple but writing non-blocking code and looping are not that easy to mix the first time. If you checkout the source code, you may notice there is unused code for word indexing. I'll use this for autocompletion suggestions when I have time.
The server queries the SQLite DB for search results and returns JSON to the search AJAX query. Here, it is really simple, just had to clean up search queries to avoid SQL injections. Some duplicated code to clean up though :$
How is it setup?
So the search indexer is ran at built time from a git hook script.
I have a bare repository (/var/www/blog_repo/) acting as a remote for both my local repo and the deployed repo (/var/www/blog/). I also have a Github repo to share this great code. When I push from my local repo, the bare repo post-receive hook is ran:
git push github master # Push updates to the Github repo
cd /var/www/blog/ # Go to the deployed repo
env -i git pull origin master # Update the deployed repo
export PATH="/var/lib/gems/1.8/bin/:$PATH"
jekyll --no-auto # Build the blog
cd /var/www/blog/search_indexer/
node search_indexer.js # Build the search index
The only thing it doesn't do is start the node server because I didn't figured out yet how to run an upstart script as a non-root user. Here's the upstart script:
description "node.js server"
author "Simon Jodet"
start on started mountall
stop on shutdown
respawn
respawn limit 99 5
script
export HOME="/var/www"
exec sudo -u www-data /usr/bin/node /var/www/blog/search/search.js >> /var/log/node.log 2>&1
end script
The good thing is that I only need to reload it when I update the search server script which is not that often.
Finally, the server is behind a Nginx reverse proxy. I'll let you search the web on how to setup Nginx as a reverse proxy. Here's the virtual host configuration:
server
{
listen 80;
server_name blog.jodet.com;
location = /50x.html
{
root /var/www/nginx-default;
}
access_log /var/log/nginx/jodet_access.log;
error_log /var/log/nginx/jodet_error.log debug;
index index.html;
location /search/
{
proxy_pass http://127.0.0.1:1337/;
}
location /
{
root /var/www/blog/_site;
}
}
Simple, right? Nginx rocks! And guess, what? It is built on an event loop too.
If you have questions or see an issue with my setup, drop me a comment please. It will be much appreciated!
Finally, my blog's code is available for all to check on Github. Apart from the blog posts, it's under the MIT license so you're free to do whatever you want with my code (but not my posts!).
blog comments powered by Disqus
Twitter feed