YAGNI

Publish a static site with Emacs

About

Emacs offers the possibility to export org files into different formats. This task can be done either by a single file or by project organized in a folder tree.

This post explains how to setup a project called "posts" that will export org files into HTML and prepare them for publishing on the web. I use a similar setup to maintain a personal blog without the need of a framework other than Emacs itself.

Project structure

A static web site normally consists of text files that provide the structure and look (HTML, JavaScript and CSS) and additional content files such as images, videos, etc. The structure of a project (named "posts" in this example) may look like this:

posts
    |-- 1.org
    |-- 2.org
    |-- css/
    |   `-- my.css
    |-- img/
    |   |-- emacs.png
    |   `-- org-mode.png
    |-- index.org
    `-- js/
        `-- my.js

In this structure, the org files are blog entries that will be exported to HTML, the rest of the files will be kept unmodified and published as attachments.

Project settings

Org-mode offers the org-publish-project-alist variable which holds a list of projects and components that will be exported and published. In this example, the "posts" project can be split in two different components:

  1. posts-to-html: for the org files that are to be exported to HTML and published
  2. posts-attachments: for the files that are to be published unmodified

Given this, the org-publish-project-alist will can be declared as:

(setq org-publish-project-alist
    `(("posts-to-html"
       :base-directory "~/path/to/posts"
       :base-extension "org"
       :publishing-directory "/ssh:user@host:/var/www/posts"
       :recursive  t
       :publishing-function org-html-publish-to-html
       :headline-levels 4
       :auto-preamble  t)
      ("posts-attachments"
       :base-directory "~/path/to/posts"
       :base-extension "css\\|jpg\\|png\\|js"
       :publishing-directory "/ssh:user@host:/var/www/posts"
       :recursive t
       :publishing-function org-publish-attachment)
      ("posts" :components ("posts-to-html" "posts-attachments"))))

The last item on the list (posts), represents the project and lists its two components.

Export and publish

With this definition now it's possible to export and publish the "posts" site using org-export-dispatch bound to C-c C-e P x posts.

See also

Created on 2025-01-12