Recently at work, I came across a documentation website recently set up for one of our APIs. I thought it looked great, and slick, and super nice, and wanted to adopt it for anther project. I was told the documentation was generated using a project called Slate, and after taking a look I knew I had to try it out. It’s very pretty.

First step: read some docs. “Getting Started with Slate” seemed like a good place to get started.

prerequisites

Mhm, looking good so far. I’ve got all those things.

setup

Hold up. What? Is this telling me that I can’t just “use” this thing to build documentation as a tool? I need to fork it and change it?

Okay great. Well, I don’t want to do that. I want my documentation to be part of my repository, so it can be versioned alongside our code, and I don’t want to carry around the baggage of an entire repository alongside my documentation. So let’s not do that, and try to hack Slate into a proper doc builder.

# Making the Script


mkdir -p docs_build
cd docs_build
if [ ! -d slate ]; then
  git clone [https://github.com/lord/slate.git](https://github.com/lord/slate.git)
fi

To start off, I want my script to grab the repo (I’ll need it one way or another) and chuck it into a temporary directory. I called it docs_build and chucked it into my .gitignore where it belongs.

Next, I’ll go ahead and symlink everything that I’m supposed to change in my “fork” from where I want my actual documentation to be — I decided to call it docs_src — into the cloned Slate repo.

# in /docs_build

# documentation
ln -fs "$(dirname "$(pwd)")"/docs_src/index.html.md \
  slate/source/index.html.md

# CSS variables (colours, etc.)
ln -fs "$(dirname "$(pwd)")"/docs_src/stylesheets/_variables.scss \
  slate/source/stylesheets/_variables.scss

# cute logo!
ln -fs "$(dirname "$(pwd)")"/.static/inertia.png \
  slate/source/images/logo.png

Note that when creating a symlink with ln -s, you should use the full directory path as your source, or the link could point to something nonexistent. In this case, I opted to use pwd and join it to the file I’m trying to link from.

Next, I’ll need to install Slate’s dependencies:

# in /docs_build

cd slate
bundle install

And hypothetically I should be good to go!

# in /docs_build/slate

# build docs into the /docs directory
bundle exec middleman build --clean --build-dir=../../docs

The build works, and all seems well. Let’s check out live reload:

# in /docs_build/slate

bundle exec middleman server --verbose

If you’re following along, you’ll probably notice that this step tragically does not work properly — editing a file in my /docs_src directory does not trigger a reload.

This probably happens because a symlink doesn’t usually play well with file watchers, and poking around the Middleman repository issues reveals a few (such as this one) that reveals this is likely the problem. Some more digging surfaces a files.watch feature that seems to do what I want: add my symlink source directories as a trigger for rebuilds.

The problem is, I need to add this to config.rb, which is in the Slate repository, and I want to maintain my Slate-as-a-doc-builder feature, which means any configuration changes I make must be scripted and perfectly reproducible.

TEMPLATE_FILES_WATCH= \
  "files.watch :source, path: File.join(root, '../../docs_src')"

if ! grep -q "$TEMPLATE_FILES_WATCH" slate/config.rb ; then
  echo "$TEMPLATE_FILES_WATCH" \
    >> slate/config.rb
fi

Nice! This script checks for if my custom files.watch directive is already in Slate’s config.rb , and if not, append it to the end. Now running the Middleman server successfully live-reloads my changes to http://localhost:4567 !

I’m not quite done though — I also want my site to have a favicon. I figured this might be a configuration option in index.html.md , but it’s not:

Hey, I just realised the author’s name is Robert as well!

Well that’s just great. Time to whip out some sed:

LAYOUT="slate/source/layouts/layout.erb"

if ! grep -q "<%= favicon_tag 'favicon.ico' %>" "$LAYOUT" ; then
  sed -i '' '/<head>/a\
  <%= favicon_tag '\''favicon\.ico'\'' %>
  ' slate/source/layouts/layout.erb
fi

This checks the layout for the favicon tag, and if it’s not there, insert it right after the <head> tag.

There it is!

Then I had to add the favicon to my list of things to symlink:

ln -fs "$(dirname "$(pwd)")"/.static/favicon.ico \
  slate/source/images/favicon.ico

And it worked! bundle exec middleman server kindly updated my local deployment to show my shiny new favicon:

Marvellous.

# Finishing Touches

Here’s what the documentation site looks like now:

Wheeee

Feel free to check out the commit or pull request that added all this stuff to Inertia, a UBC Launch Pad project!