Published: January 17, 2021

Emacs as a Static Site Generator

I’ve been hosting my website on GitHub Pages since 2014. Over the years I have tended to rewrite my website whenever I was learning a new programming language.

I started out with a “pure” HTML+CSS website and eventually moved on to Python, where I used the Frozen-Flask package to bundle my Flask app into a set of static files. As time went on, I started writing my own static site generators: first in Bash+Pandoc, then Common-Lisp, and later Go(lang).

Overall I have enjoyed writing my own static site generators and think it’s a great project for exploring a new programming language. In fact, whenever I’ve tried migrating to one of the popular options like Hugo, I ultimately went back to doing it myself because I hated dealing with auto-generated files, customizing themes, and digging through incomplete documentation.

I have been using Emacs and Org Mode for a long time but never explored the org-publish functionality. It’s far from perfect, but it’s incredibly convenient. Like most things Emacs, org-publish can be configured to do just about anything. So far I only use it to generate this website, but my configuration can be easily extended to handle several different projects.

This website is generated from Emacs using M-x org-publish

(require 'ox-publish)

(defvar my/website-org-path "~/src/")
(defvar my/website-org-base-directory (concat my/website-org-path "/org/"))
(defvar my/website-org-publishing-directory (concat my/website-org-path "/public_html/"))
(defvar my/website-head-extra
  (let ((viewport "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />"))
    (concat viewport "\n")))

(setq org-html-metadata-timestamp-format "%Y-%m-%d")
(setq org-html-htmlize-output-type 'inline-css) ; Uses current theme for syntax highlighting
(setq org-publish-project-alist
        ("website" :components ("website-content" "website-static"))
          :base-extension "org"
          :base-directory ,my/website-org-base-directory
          :publishing-directory ,my/website-org-publishing-directory
          :publishing-function org-html-publish-to-html
          :recursive t

          ;; Disable some defaults
          :html-link-home ""
          :html-link-up ""
          :html-head-include-default-style nil
          :html-head-include-scripts nil
          :html-preamble nil
          :html-postamble nil

          ;; Custom options
          :headline-levels 4
          :language "en"
          :html-html5-fancy t
          :html-head-extra ,my/website-head-extra
          :with-date t
          :with-emphasize t              ; *:t
          :with-smart-quotes t           ; *:t
          :with-sub-superscript nil      ; ^:nil
          :with-toc nil                  ; toc:nil
          :section-numbers nil           ; num:nil
          :html-preamble "<p>Published: %d</p>"
          :html-postamble "<p>Last updated: %C</p>"
          :html-wrap-src-lines t)

          :base-directory ,my/website-org-base-directory
          :publishing-directory ,my/website-org-publishing-directory
          :base-extension "css\\|js\\|jpg\\|png\\|pdf"
          :publishing-function org-publish-attachment
          :recursive t)))

Last updated: 2023-01-12