Turning Slate into a proper documentation builder

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

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.

Image for post
Image for post

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

Image for post
Image for post

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?

Image for post
Image for post
…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:

Image for post
Image for post
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.

Image for post
Image for post
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:

Image for post
Image for post
Marvellous.

Finishing Touches

Here’s what the documentation site looks like now:

Image for post
Image for post
wheeeee

Written by

📊 software engineer | more posts and goodies at bobheadxi.dev

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store