Including code snippets into a blog post, such as my recent post switching a Hugo theme typically means copy-pasting snippets into your blog post text, surrounded with code fences, but makes the code unusable (it can no longer be compiled or analyzed). Similarly with the output of any given command, log file, etc.

Thus, we keep the canonical copy of the code (or the output) in an external file, and have to periodically manually copy-paste the content back into the blog post, but of course, if we forget, it’s out of date. What if we fix a bug in the code, and forget to include that fix into the blog post? Inaccuracies will confuse our future readers.

How can we automate this process?

What we need is a way to keep not just the canonical but the only copy of the code outside of the Markdown file we’re using to publish our blog post, such that it’s the one always in use by our build and run steps, and the blog post is automatically using the latest and greatest version that we have.

What we can do is use a feature of Hugo called shortcodes:

A shortcode is a simple snippet inside a content file that Hugo will render using a predefined template.

Hugo provides a rich programming environment that can do quite a lot, so thanks to a Stack Overflow answer, here’s what we can do:

  1. Create the file layouts/shortcodes/code.html in your repo with the following contents:

    {{ $file := .Get "file" | readFile }}
    {{ $lang := .Get "lang" }}
    {{ (print "```" $lang "\n" $file "\n```") | markdownify }}
  2. Now, when I create a file such as content/blog/2019/05/some-post.md that needs includes, I will also create a sibling directory, namely content/blog/2019/05/some-post/ that will house the code files, Makefiles, Dockerfiles, etc.

    Alternatively, you can just create a directory content/blog/2019/05/some-post/ and put the post itself into that directory as well, named index.md, since each post becomes a directory in the file tree.

  3. Then, to include the code into the post, I use a path to the file, relative to the content/ directory, e.g.,

    {{% code file="blog/2019/05/some-post/Dockerfile" lang="docker" %}}

Note: if you want to actually display shortcodes verbatim in a code region as I did above, you cannot simply write {{% %}} as it will give you an error; instead you need to escape the internal contents of the {{...}} with /* ... */. For details, see this very helpful blog post.

Now you will be able to keep your code compilable and testable, avoid errors when manually copying or sourcing in files into your blog posts, and always know you’re getting the latest version of your code snippets in your blog posts, automatically!

Since learning about this very simple approach to custom shortcodes via the Stack Overflow answer above, I’ve updated my recent blog post switching a Hugo theme to use these shortcodes and moved all the Dockerfiles code, including the diffs, into external files such that they’re easily accessible via the docker CLI tool.