Jekyll on Rails

By Jesse Herrick


We can all appreciate the power that Ruby on Rails gives us to rapidly build great web applications. We can also appreciate Jekyll’s amazing ability to turn Markdown and templating into a beautiful static site.

What if we could combine these two? In this article, I’m going to do just that.


The most practical scenario to combine Jekyll and Rails is when you don’t want to separate your main app from your blog. You shouldn’t do this if you just want to add some dynamic-ness to your site (Middleman is better suited for this). But whatever the reason may be, let’s get started!

Step 1: The App

In the most likely scenario, you probably already have an app and you’d like to add a blog. However, for the sake of uniformity, let’s generate one for our purposes:

$ rails new jekyll-on-rails
$ cd jekyll-on-rails

Now that we’re in the app, we need to set it up for our Jekyll blog. First, we should add Jekyll to the app:

# 'Gemfile'
gem 'jekyll', '2.5.3'

# Terminal
$ bundle install

Once this command is complete, we can begin adding our blog to Jekyll.

Step 2: The Blog

Hypothetically, all Jekyll needs to run is a template file and a Markdown file. But we have blogs that are more complicated than that. Every blog is (and should be) different, but we need a uniform blog to demonstrate with, so let’s use the default.

First, let’s have Jekyll generate our blog.

$ bundle exec jekyll new blog

This creates a simple blog example with this file structure:

├── _config.yml
├── _includes
│   ├── footer.html
│   ├── head.html
│   └── header.html
├── _layouts
│   ├── default.html
│   ├── page.html
│   └── post.html
├── _posts
│   └── 2015-03-27-welcome-to-jekyll.markdown
├── _sass
│   ├── _base.scss
│   ├── _layout.scss
│   └── _syntax-highlighting.scss
├── css
│   └── main.scss
├── feed.xml
└── index.html

We’ll leave most of these where they are, but we’re going to move _config.yml into the Rails config directory and rename it something more specific:

$ cd blog
$ mv _config.yml ../config/jekyll.yml
$ cd ..

This is where the fun really begins, configuring the blog!

Step 3: Configuring the Blog

If you try going into the blog right now and running jekyll serve, it will still work, but you’ll get an error that there is no configuration file. This is obviously because we just moved it, so we’ll have to use special configuration when generating our blog.

We want the Jekyll site to be built every time that our Rails app is regenerated, so we need to add an initializer to our app:


Rails.application.config.after_initialize do
  Rails.logger =
    # make a spot for the site
    dest = Rails.root.join('public/blog')

    # generate the site
        "config" => Rails.root.join('config', 'jekyll.yml').to_s,
        "source" => Rails.root.join('blog').to_s,
        "destination" => dest.to_s

                # the strange codes give the output color "\e[0;32;49mJekyll site built!\e[0m]]"
  rescue => e
    Rails.logger.error "\e[0;31;49mJekyll site build failed.\e[0m\n\e[0;33;49mError:\e[0m #{e}"

This code does a few things for us:
* It generates the Jekyll site when the Rails application starts
* It defines a path for the site to be at (http://localhost:3000/blog/) – to change this path, modify the dest variable
* It uses smart error handling to ensure that we know when the site build succeeds and when it fails. This also ensures that, even if the site build fails, the application will not fail, allowing for a separation of code bugs between Jekyll and Rails

This file tells Jekyll to take our site (in blog/) and move it to (public/blog/). This only works because Rails hosts static files in its public/ directory.

Now we can finally start our Rails app and see how this worked!

$ bundle exec rails server
=> Booting WEBrick
=> Rails 4.2.0 application starting in development on http://localhost:3000
=> Run `rails server -h` for more startup options
=> Ctrl-C to shutdown server
Configuration file: /Users/jesseherrick/Dropbox/Drafts/jekyll-on-rails/config/jekyll.yml
I, [2015-03-27T16:08:02.591221 #56341]  INFO -- : Jekyll site built!
[2015-03-27 16:08:02] INFO  WEBrick 1.3.1
[2015-03-27 16:08:02] INFO  ruby 2.2.0 (2014-12-25) [x86_64-darwin14]
[2015-03-27 16:08:02] INFO  WEBrick::HTTPServer#start: pid=56341 port=3000

But there’s a problem, the CSS wasn’t loaded properly!


With a little investigation, you’ll notice that the HTML uses absolute paths (i.e. /css/main.css). This means that any assets being requested will return a 404 because our blog is in a subdirectory. Luckily, the Jekyll site template is smart enough to have a baseurl option in the config, which allows for the definition of a subdirectory for asset loading. To quickly fix this problem, we can change our config like so:

# ... other config not shown ...
baseurl: "/blog"
# ... other config not shown ...

We use /blog because it is the directory where our site is generated. Once we restart the server, everything seems to be working fine.


And there you have it, a Rails app and Jekyll site working seamlessly together. You can stop reading now if you’d like, but there’s more cool stuff coming up.

Extra: Using Rails-like Assets

Unfortunately, there isn’t a way at the moment to link Rails assets into Jekyll easily. But if you still like the Rails asset pipeline (come on, who doesn’t?), there’s a plugin for that!

Jekyll-Assets is a fantastic Jekyll plugin that can do a lot of things for you, like:
* Compile CoffeeScript, SCSS/Sass, Less, and ERB
* Require dependencies from inside assets (using Sprockets)
* Hard and soft cache busting (main-bbd8a1c8b716f90cfaf9493cbb3868dc.css vs main.css?cb=bbd8a1c8b716f90cfaf9493cbb3868dc)
* Compress your assets
* And a few other things

That’s pretty awesome, right? Let’s add it to our Jekyll site.

First, we add gem 'jekyll-assets' to our Gemfile and bundle install. Next, we need to make sure that Jekyll includes this plugin when generating the site. To do this we just add jekyll-assets to our list of plugins in config/jekyll.yml, like so:

# 'config/jekyll.yml`
  - jekyll-assets

# ... other config ...

Now that the plugin is added into Jekyll, we can start using it. But first, we should configure it for the features that we want. So open up config/jekyll.yml again and put:

# 'config/jekyll.yml'

# assets
    dirname: assets # _assets
    baseurl: /blog/assets/
    sources: # asset subdirectories
        - _assets/stylesheets
        - _assets/javascripts
        - _assets/images
    cachebust: hard
    js_compressor: uglifier # included by rails
    css_compressor: sass # included by rails

# ... other config ...

Awesome, but now we have to actually utilize this plugin. To do that we need to move around our assets:

# make a place for the assets
$ cd blog
$ mkdir _assets
$ mkdir _assets/stylesheets
$ mkdir _assets/javascripts
$ mkdir _assets/images

# move around assets
$ mv _sass/* _assets/stylesheets/ && rmdir _sass
$ mv css/* _assets/stylesheets/ && rmdir css

If we happened to have any JavaScript/CoffeeScript files and/or images, we would move them into their respective folders as well.

Just like in Rails, Jekyll-Assets uses double (and sometimes triple) file extensions to convert files. For our purposes, we should rename main.scss to main.css.scss because we want our files to be parsed as SCSS, then converted into CSS. You should do this with any files that you want Jekyll-Assets to convert (e.g.

If we take a look at our blog again, you’ll notice an issue. The stylesheets are 404ing again. To fix this we just need to implement Jekyll-Assets’ way of linking stylesheets (and scripts) into HTML.

Jekyll-Assets provides several liquid tags and generators to properly implement cache busting and asset path handling. We won’t cover them all here, so take a look at this page if you’re curious.

To link our stylesheet, we just need to add this to our HTML :

<!-- 'blog/_includes/head.html' -->
{% stylesheet main %}

Now we can delete any old tags as they will just throw 404s. And if we restart the app, you’ll see that the stylesheets are once again being loaded.

Why did we just go through all that trouble to get the same result?

Although that seemed redundant, we actually setup a very nice system for ourselves. Let’s add some CoffeeScript to demonstrate this.

Let’s say that I want to add FitText.js to my Jekyll site so that the title is awesomely responsive using JavaScript. The problem is that this script relies on jQuery for its functionality and I don’t want to make a lot of script calls in my HTML for performance reasons. Jekyll-Assets makes this really easy to do.

First we need to open up the Jekyll config and add a new subdirectory into the JavaScript assets folder:

# 'config/jekyll.yml'

  # ... other config not shown ...
          - _assets/stylesheets
          - _assets/javascripts
          - _assets/javascripts/vendor # added
          - _assets/images
        # ... other config not shown ...

Now we need to make that vendor directory and download jQuery and FitText.js into it:

# create the directory
$ cd blog/_assets/javascripts
$ mkdir vendor
$ cd vendor

# download the assets
$ wget -O fittext.js
$ wget -O jquery.js

Combine the files so there won’t be multiple requests for the javascript:

# 'blog/_assets/javascripts/
#= require vendor/jquery
#= require vendor/fittext

# and then actually use the plugin

Finally, request that one script in the HTML:

<!-- bottom of '_layout/default.html' -->
{% javascript main %}

Now, if we reload the page, we get a nice big responsive heading:


This is just the beginning of what you can do with Jekyll-Assets.

Jekyll has a fantastic community that makes great plugins, but if you’d like to create your own Jekyll has docs for that too.

Extra: Automation

You probably noticed that we have to keep restarting Rails every time we want to preview the site. That’s fine if we’re just making a few changes to the Jekyll site, but if we’re doing web design, it can get pretty annoying. Luckily we can automate this!

First, generate a new Rake task for Rails.

$ rails generate task jekyll

This command creates a file called lib/tasks/jekyll.rake. Using Jekyll’s API, we can programmatically build the site and serve it at the same time (using threads).

namespace :jekyll do
  dest = Rails.root.join('public/blog')

  options = {
    'baseurl' => '/blog',
    'config' => Rails.root.join('config', 'jekyll.yml').to_s,
    'watch' => true,
    'port' => 3000,
    'source' => Rails.root.join('blog').to_s,
    'destination' => dest.to_s

  build = { Jekyll::Commands::Build.process(options) }
  serve = { Jekyll::Commands::Serve.process(options) }

  commands = [build, serve]
  commands.each { |c| c.join }

Now, rake jekyll, will start the server at http://localhost:3000/blog/ and reload itself whenever file changes are detected.


The possibilities with Jekyll and Rails are endless. This seemingly opposite pair can work together in perfect unison for a great, well-rounded website. You can find the source of this project on GitHub. I’d love to hear your input below if you have any questions or a suggestion on how this method could be improved.




Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Ruby, once a week, for free.