I'd been meaning to build a blog for a while but had never really gotten around to it. I, like many others I'm sure, briefly considered having a go with Wordpress but after spending all of 5 minutes reading their installation instructions I decided against it. Setting up a database, FTP transfers (granted other publish methods likely exist), faffing with web host settings etc. It all felt a bit early 2000s.
On my daily travels through the interwebs I learned of Jekyll. I was sold by the idea of being able to work on posts in markdown and being able to simply push to my Github repo to publish. Up to that point I didn't know that's how many Github projects write and maintain their pages or blogs.
Like all these things, one starts with the idea and then begins thinking of things one would like it to do and how it would look. I did a few sketches of how I'd like it to look and listed a few basic requirements.
Below I set out some basic information on how I put this together for anyone with similar requirements who might chance upon this post. It'll help you get started.
I think it's always helpful when reading "how I did this" posts to know what the general set up is as it can sometimes make a difference. So, with that in mind here is mine:
- OSX 10.9.2
- homebrew-managed packages
brew-installed Ruby and
- zsh as my shell du-choice (surely invalid French) managed by ohmyzsh
- Chrome and its devtools.
- LiveReload with its Chrome browser extension
brew-installed Node (
$ brew install node)
npm-installed GruntJS command line interface (
$ npm install -g grunt-cli)
OK, that list seems like a fair bit, but they're all easy things to set up and all things I already had because I use them daily.
So here's a basic list of what I wanted for my blog:
- A simple-looking blog with a basic sub-page categorisation of stuff I'm interested in : tech stuff, learning, and everything else.
- A look I can control myself.
- Comments I don't have to manage myself.
- Some automation for creating posts and drafts.
- A categorisation and tags system.
A quick look around on Stack Overflow and Google suggested this was all possible with stuff I already knew. So off I went.
Way more (and possibly accurate) info of what follows can be found on each project's site, so head there for more details as needed.
As described in the Jekyll docs for me on OS X all that was needed was to install the latest stable realease by typing into the terminal:
$ gem install jekyll -v '2.0.0.alpha.1'
This gives access to a
jekyll command through the terminal. Right?. Well, If I typed
jekyll help at the terminal I got a "command not found" response. Hmmm. Over to Stack Overflow I went and came across this post detailing a similar problem. My problem showed similar symptoms but my solution was slightly different.
The problem was essentially that there was no symbolic link from
/usr/bin to the path where the brew
gem-installed Jekyll had been installed (somewhere in the Cellar) and my
PATH variable wasn't searching there. I didn't want to have to edit my
PATH variable every time I did this, so my solution was to simply symlink to
jekyll like so:
$ gem env # Some Ruby env paths here - /usr/local/Cellar/ruby/1.9.3-p194/lib/ruby/gems/1.9.1 # Some more output here # Look in the above path for the jekyll binary # and paste its path below to create the symlink $ cd /usr/bin && ln -s /usr/local/Cellar/ruby/1.9.3-p194/lib/ruby/gems/1.9.1/gems jekyll-1.4.3/bin/jekyll jekyll
Now all was well if I typed
jekyll help at the terminal.
At this point Jekyll is installed and ready to roll. But what directory structure does it expect and how does it all work?
I learn best from playing with something as opposed to reading docs, so I found a great post by Garry Welding which I cloned and used as a starting point as he suggested. Thanks Gaz!
$ git clone https://github.com/gkwelding/gkwelding.github.com.git coderigo.github.com
If you open it up you'll see a directory structure a bit like this:
$ tree -L 1 . ├── CNAME ├── README.md ├── Rakefile ├── _config.yml ├── _includes ├── _layouts ├── _plugins ├── _posts ├── _site ├── atom.xml ├── css ├── favicon.ico ├── img ├── index.html ├── js ├── search.json └── tags
It looks like a fair bit and the best way to get familiar with it is to run
jekyll serve --watch on it, which will start a web server, and edit stuff to see what it does. It took me maybe 30 or so minutes to begin to understand how it all works. Here are a few noteworthy points:
- All the directories beggining with
_are inputs into Jekyll's build process and it either expects them (e.g.
_posts) or knows they are options.
- An exception to the above point is
_sitedirectory, which is the built/processed version of your website ready for publishing. If you publish your repo to your Github account, Github will effectively run
jekyll buildon your repo and serve out your
_sitefolder to the public.
_config.ymlis the config file where you can set different markup languages, ignore directories when building, etc. The docs are pretty good on what you can include in this file.
Rakefileis a file that automates things like creating draft and new posts. I use Grunt instead, so I ended up not using this.
CNAMEfile simply lets your Github-served blog e.g (coderigo.github.io) to also be served from a domain you own (e.g. rodrigomartell.com).
- Anything placed in the root directory that Jekyll doesn't know about/expect will be copied over when the site is built. If you want it to ignore stuff, tell it so in
_layoutshelp a lot to DRY out your templates. It uses liquid templating, which isn't that difficult to feel your way through. It felt very much like AngularJS templates to me.
- Loading of Disqus comments can be made by going to your Disqus account and simply pasting their provided embed code in the appropriate file in
So, with my requirements in mind I made a number of changes to:
- Include Bootstrap 3
- Use Grunt instead of Rakefile to automate tasks (including serving of the built site). I based it off what I saw here and here.
- Add my own style and use
solarized-darkcss theme for code highlighting.
- Add drafts as described here
- Add LiveReload to make development easier
Feel free to clone my repo and use as a base like I did Garry's.
Writing drafts and posts
With Grunt I can then start a server like so:
# from the root of my project $ grunt Running "startServer" task Running "shell:jekyllBuild" (shell) task Configuration file: /Users/rodrigomartell/dev/coderigo.github.com/_config.yml Source: /Users/rodrigomartell/dev/coderigo.github.com Destination: /Users/rodrigomartell/dev/coderigo.github.com/_site Generating... done. Running "connect:livereload" (connect) task Started connect web server on http://localhost:9000 Running "watch" task Waiting...
LiveReload takes care of refreshing the page after I change any files in the spots I told Grunt to watch in
I open up another terminal window where I can create drafts like so:
# from the root of my project $ grunt draft:"A draft post"
This Grunt task will create a post based on the templates I set up in the
grunt_templates directory. It makes sure the files are copied to the right places and named like Jekyll expects (spine-casing slugs and file names).
When I'm ready to promote a draft to a post I use grunt again like so:
# from the root of my project $ grunt promoteDraft:"_drafts/a-draft-post.md"
That moves the post from
_posts, renaming it the way Jekyll expects and filling in today's date.
I can also jump straight into creating a post without drafting it if I'm feeling cocky:
# from the root of my project $ grunt post:"A post"
This is perhaps the sweetest part. To publish your post you simply commit your changes to the repo and push up to a repo on Github you've set up that follows the naming convention
<your github username>.github.com. So mine would be
coderigo.github.com. Note that you must push to the
master branch any changes you want Github to build as it ignores any others.
Github will take care of the rest for you. You might have to wait a few minutes before you can see your changes take effect.
$ git add _posts/ $ git commit -m "Add new posts" $ git push origin
I'm by no means an experienced Jekyll user but I can already see that I will be using it a lot, seeing what it can do and learning as I continue to play with it.