Setting up a static site with emacs org-mode

Home | About | Items

31 August 2024

I looked at static site generators and while some of them are impressive, they're possibly too complicated for my needs. I just wanted something that can take what I write in org-mode with its simplest features, and turn it into something readable to publish. It turns out as many have previously discovered, this is yet another task org-mode can help with. So here is my setup.

Setting up org-publish

I created a git repo with the following in .dir-locals.el:

((nil .
  ((org-publish-project-alist
    . (("site"
        :base-directory "~/dev/codeberg/site"
        :recursive t
        :exclude "\\(?:\\(?:draft\\|inc\\)/\\)" ; (rx (or "inc/" "draft/"))
        :publishing-function org-html-publish-to-html
        :publishing-directory "~/dev/codeberg/site/public_html"
        :with-author nil
        :with-creator nil
        :with-toc nil
        :time-stamp-file nil
        :section-numbers nil
        :html-doctype "html5"
        :html-html5-fancy t
        :html-head "..."  ; omitted
        :html-head-include-default-style nil
        :html-head-include-scripts nil
        :html-postamble nil
        :html-use-infojs nil))))))

This makes C-c C-e P p generate HTML files into public_html. I then run a local web server (I happened to have npx serve from having tried out Eleventy earlier, so I use that) and verify that things work as they should. Then I copy the files from public_html up to the pages repo which gets published on Codeberg Pages.

Makefile

Because I always forget commands after a week goes by without using them, I generally put useful things in a Makefile.

.PHONY: all
all:
        emacs index.org --eval "(progn (org-publish-all t) (kill-emacs))"

.PHONY: serve
serve:
        npx serve public_html


.PHONY: install
install:
        cp -R public_html/* ../pages/

Headers and footers

This was a bit more of a pain than it should have been, because org-mode insisted on doing strange and unpredictable things with relative links. In the end, I used HTML in my inc/header.org file, and included header.org and footer.org files in each subdirectory, which in turn include the canonical ones in the inc directory.

So an item can simply have the following at the top of the file

#+title: Setting up a static site with emacs org-mode
#+include: "header.org"

and this at the bottom:

#+include: "footer.org"

Update 12 September 2024

A conversation with someone on Mastodon reminded me there's a surprising behaviour when you're first setting up a .dir-locals.el file: edits to the file do not have any effect, unless you cause emacs to reload a buffer in the directory tree affected by the .dir-locals.el file.

The most typical way to reload a buffer is of course to kill the buffer and reopen it. But a faster way is to simply invoke M-x normal-mode on the buffer.

You'll know it's worked when emacs asks you again if you want to mark the variables as safe. If you're like me and kept tweaking the various values in that file, you'll end up with many, many entries in your init.el file, one for each time you answered '!' to the challenge. You can delete all but the topmost one.



Contact: @mocom@mastodon.social. Published using C-c C-e P p. If you use this content commercially, kindly make an appropriate donation to Zig Software Foundation in my name.