Org-mode and Pandoc as a static site generator
目录
I've spent a lot of time looking for the "perfect" static site generator. I want something that's:
- fast
- simple enough to let me focus on writing
- easy to run on someone else's server
- extendable if and when I want to
While there are some awesome site generators out there now (I really enjoyed hugo for it's 0 dependencies and speed) most were just too big for me. They had specific templating systems, or required set up and theming that I didn't want to get into.
I settled on using pandoc to convert a set of markdown files to html, and paired it with a very simple css file. This worked well! I had an ultra-minimal blog generator that I could run on Gitlab Pages super easily.
Eventually though I ran into the limitations. I wanted to generate an index page for the blog, as well as a fancier table of contents for a whitepaper. To handle this I ended up adding cases to what was a pretty small bash script. And of course that became a pain to maintain.
The main problem was a separation between the writing I wanted to do and the code I had to write to manage it. What if these could be tied together? I'd had some exposure to the ideas of Literate Programming from Donald Knuth, but it had never really clicked for me in a practical way.
This changed as I started using the wonder that is org mode. Bear with me, I'll get to blog generation soon.
What is Org Mode?
Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text system.
Org is a joyful piece of software. It's a simple yet powerful combination of intuitive markup and ergonomic tooling that (most of the time) just works. The key is that the markup is readable at a glance, and the tools provide some pretty neat ways of interacting with and manipulating it.
It's core components are fairly simple:
headings
, lines which start with a number of*
's, provide top-level structure,- inline markup like
* *
and/ /
provide styling - blocks (denoted with
#+
) provide space to do some really cool stuff. keywords like
TODO
work with specific tools and provide contextThis all comes together perfectly as a tool for literate programming.
Literate blog generation
You may have noticed the source blocks scattered around this site. They define how the content under them is generated. They're just code blocks, but with org-babel I can execute them right in my editor to generate those blocks on the fly! For the site I'm using bash, but babel (as the name implies) let's you write in pretty much anything.
Build the blog list with bash
Is this a little overkill? Yes. But it's way more maintainable than the monster bash script I was using previously.
It's probably not the static site generator for you if you just want to get to blogging, but it's incredibly fun to put together and a great learning experience.
Having the code in the same place as the writing you do encourages you to both maintain it and write more. This could turn into an endless bikeshed, but for me it opens up a ton of possibilities in producing the kind of work I want to.
Getting Started
Org-babel's documentation is somewhat scattered but digging through The Org Manual eventually got me where I needed be. This article on using it for Literate Dev-Ops by Howard Abrams also has a ton of useful information and techniques.
How this site is actually built
The rough idea is to have a bunch of code snippets distributed throughout the site in org-babel blocks. Then we use blocks that look something like this at each level up.
(find-file "./blog/index.org") (org-babel-execute-buffer ) (save-buffer)
This will go into a specific file and execute all the org-babel blocks contained within. And if that file includes a similar block, it'll go down into others!
And at the top level (the index.org
file) we have the code that starts it all.
Getting some HTML
Once all the files are set up, we have a small bash script right at the top to convert all of that markdown to html.
#!/bin/bash rm -rf _public root="$(pwd)" #emacs --batch -l ./build-assets/build.el for folder in $(find . -type d -not -path '*/\.*'); do (cd $folder for file in `find . -maxdepth 1 -name "*.org"`; do [ -e "$file" ] || continue mkdir -p "$root/_public/${folder#./}" pandoc -f org -t html "$file" \ -o "$root/_public/${folder#./}/`basename "$file" .org`.html"\ --lua-filter $root/scripts/changeLinks.lua \ --lua-filter $root/scripts/task-list.lua \ -B $root/static/html/header.html \ -H $root/static/html/includes.html \ -c "/static/styles.css" \ -s done) done cp -r static _public/
It's pretty small as the heavy lifting is done by pandoc. This time however, this script can stay small as we're letting org-babel take the weight.
What's next?
Well actually writing for one. I've got the infrastructure in place and now it's time to start using it!
Well, there's also some additional infrastructure I'd like to get in of course :)
- Get a git-hook in place to run the top level script whenever I commit
- Figure out how to handle comments or replies
[0/2]
Tie my other org files to the site:- TODOS,
- Links