Turning Slate into a proper documentation builder

No thanks I don’t want to fork your repository. 😶

Robert Lin
Feb 9 · 5 min read

I’m currently working with RTrade Technologies, Ltd. and a documentation website was recently set up for one of our APIs. I thought it looked great, and slick, and super nice.

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.

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

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?

…uh

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

No! Not the Script!
mkdir -p docs_build
cd docs_build
if [ ! -d slate ]; then
git clone 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_buildcd 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/slatebundle 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 realized 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:

wheeeee

Robert Lin

Written by

📊 more posts and other stuff at bobheadxi.dev

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade