Heikki @ home

Loose leaves from my tree

Understanding org-page

I spent some time looking for a really simple platform for blogging. Simple in the sense that I can control everything from emacs and do not have to worry about clicking with a mouse a dozen times to get something done.

I tried Octopress and Nikola, but could not get neither to run easily. From these experiences I knew I wanted something that worked with org mode and created static pages. The org-page package worked at first try and fulfilled both requirements. I did have to scrap my first attempt because I realized I had not understood how org-page works. The project documentation is sparse so it is easy to get lost. It has been written by a developer to developers. Let's see if I can spell out the self-evident.

How does it work?

org-page are has three local components, and at least one remote. These are:

  1. local org-page code base that manages everything, installed in emacs
  2. local source branch of your web-site
  3. local master branch generated from source by the code base
  4. remote master branch serving HTML pages
  5. (remote source branch)


The optional remote component of source does not really do anything, but it is a nice way of creating a backup and safeguarding your work.

Note that remote does not have to be in remote computer: You save the output to any local directory that your web server can see, e.g. http://localhost/~your_login.

By branches we mean branches of a git repository. Everything in org-page is based on git and you have to have some kind of understanding of its workings before you can make org-page to do what you want. Commonly git branches contain files that have at some point been the same and will at some point be merged back together. Org-page branches are different. The source branch holds org mode files that the code base will translate to HTML for publishing. To keep things simple, you should keep the flow of information one way only.

This was my initial stumbling block. I kept switching between the two branches and did not know what to commit where. In no time the repository was a complete mess. The code base does not know in which branch the repository is and does not warn you. It would be great if it were to know and refuse to touch files in a wrong branch.

Starting anew, I was more careful.


The whole idea of org-page is that the software can automatically push the latest updates to the server. It comes with several documented options of doing it but it has really designed to take advantage of GitHub's feature that a public repository named {yourlogin}.github.io is assumed to contain a website is automatically served out at http://yourlogin.github.io.

That's where your master branch will end up. It needs to contain HTML source code and a bit of JavaScript supported by CSS that a web server can make available to the net.

Look and feel

The org-page only has only one maintained theme, mdo. The whole project is still maintained by one person, Kelvin Hu, and his site using org-page is all in Chinese. This shows in the design. Luckily there is a way to add themes and remove some these quirks.

I copied the default theme and renamed it to sans. This has to be done in the source branch:

cd (op/repository-directory)
mkdir themes
cp -r .../org-page/themes/mdo themes/sans

I've tried to change as little as possible. The default font is of sans serif type rather than a fixed width one. The sans theme headers start now left of the body text and there is no need to add extra characters around links or bold text. In Latin text there are standard ways of rendering these features.

The only non-intuitive thing about themes is that its items are kept in a cache variable that has to be emptied before anything is visibly changes in the published web pages. More about that later.

I've copied over from the mdo theme a recent addition of table of contents. Note that toc is nil by default in org #+OPTIONS: line of entry documents and has to be set to 't' for the table of contents to be generated.

In org-page, you are expected to edit the top index page by hand. The top index.org file is created by the repository creating emacs functions. You can, however, remove that file for the org-page to create a listing of written entries. By default, these pages belong to category blog, and are located in the source sub-directory 'blog'. You can have more categories by creating new sub-directories and adding entries into them. You can decide yourself what there categories are and what kind of articles you store in them. They all share the same tag namespace and are listed in the same RSS file. Here is one installation of org-page using multiple categories.


Org-page comes with lisp functions that do everything you need to write and publish a blog.

  • op/new-repository – interactively fills in repository details and creates basic files needed
  • op/new-post – adds org headers interactively to a new buffer
  • op/do-publication – interactive, publishes either to local dir or upstream

The op/new-repository creates files based on your setup. Here is mine:

(require 'org-page)
(setq op/repository-directory "~/src/org-page/heikkil.github.io")
(setq op/site-domain "http://heikkil.github.io")
(setq op/personal-avatar "https://avatars0.githubusercontent.com/u/75674?v=3&s=460")
;; for commenting; disabled for now
;;(setq op/personal-disqus-shortname "your_disqus_shortname")

;; analytics set up at ~/.emacs.secrets file
;;(setq op/personal-google-analytics-id "UA-NNNNNNNN-N")

(setq op/personal-github-link "https://github.com/heikkil")

(setq op/site-main-title "Heikki @ home")
(setq op/site-sub-title "Loose leaves from my tree")

;; set up my own theme since a sans option does not exist
(setq op/theme-root-directory "~/src/org-page/heikkil.github.io/themes")
(setq op/theme 'sans)  ; mdo is the default

Once all is set up, run op/new-repository to a create basic collection of files and a git repository in the directory.

The op/new-post asks for a name for the entry and creates the file and org headers for you. Then you just write the content of entry and publish it. Org mode text gets converted to HTML and pushed to the remote.

The all too self-evident thing that the documentation fails to mention is that you have to commit your change before it can be published. If you have several articles under preparation that you have already added to git, you have to know how to use git stash to store the unfinished articles while you publish one.

The op/do-publication function has five arguments that can be filled in interactively to publish exactly how you want. To get those arguments right needs careful concentration. Better automate it. I am using the hydra package to help me remember the most important options. The most common command that I use pushes the last commit to the remote with C-c p l. Hydra also helps me to clear the cache when needed. Finally, C-c p t lets me test the site in a local directory.

     (kbd "C-c p")
     (defhydra hydra-blog (:color blue :hint nil)
    blog  _n_: new post                        _l_: publish last commit
          _r_: reset & publish all             _p_: publish interactively
          _t_: reset & publish to /tmp/blog    _e_: new-repository
       ("n" op/new-post)
       ("r" (progn
              (setq op/item-cache nil)
              (op/do-publication t nil nil t t)))
       ("t" (progn
              (setq op/item-cache nil)
              (op/do-publication t "/tmp/blog" nil t nil)))
       ("l" (op/do-publication nil "HEAD~1" nil t t))
       ("p" op/do-publication)
       ("e" op/new-repository)))