How to set up a Jekyll blog on Heroku

18 May 2013

While setting up this blog, I ran into an issue trying to deploy to Heroku successfully. The deploy would succeed, but then I would get the big ‘Something went wrong’ page from Heroku! What was going on? Better check out the logs:

     ERROR: YOUR SITE COULD NOT BE BUILT:
            ------------------------------------
            Post 0000-00-00-welcome-to-jekyll.markdown.erb does not have a valid date.

Full output here in a gist.

Since I had only installed Jekyll a few minutes beforehand, I was quite confused as to the source of this error. I noticed that I had a file similar to that in the _posts directory but it had a different date. Looking through the log a bit more, I noticed that it was looking in vendor! What the heck? I don’t have a vendor directory locally! What’s going on?

Here’s what happened:

  1. You deploy to Heroku
  2. Heroku decides to install your gems to vendor
  3. Heroku then uses foreman to start your web app (check out the docs),
  4. Jekyll boots and then promptly explodes because it’s processing all files in vendor that end in .erb (where the Jekyll template lives)

You can reproduce the error by installing the gems with Bundler to vendor with the --path vendor option:

bundle install --path vendor
bundle exec jekyll serve

To fix this problem, we’re going to modify the _config.yml file that determines which options that Jekyll launches with. Adding vendor to the exclude: option will tell Jekyll to not generate copy and process any files from the vendor directory.

Your _config.yml file should look something like this:

name: Your New Jekyll Site
pygments: true
exclude: ["vendor"]

Now your Heroku app should work!

Caveats Looking Forward

So you’ve discovered that Jekyll will load any directory. Did you know that it also applies to files in the root directory? Let’s make a request for Gemfile:

$ curl http://localhost:5000/Gemfile
source "https://rubygems.org"

gem 'foreman'
gem 'jekyll'
$

Woah, didn’t mean to expose that information to the public! So what can we do? We can:

  1. Add more items to the exclude: list in _config.yml
  2. Prefix the filename with an underscore if possible
  3. Nothing else

That’s it, unfortunately. Also, we can’t use include: to combat this problem. The include: directive does not mean only include these files, but rather additionally include these files as Jekyll doesn’t load files beginning with . (such as .htaccess which is the default include: setting) or _ (file or directory alike). Perhaps in the future there’ll be more fine-grained control for Jekyll so that you can specify a list of directories and files to use.

If you’re interested in reading more about Jekyll configuration, you can read their docs.

comments powered by Disqus