How To Create and Publish Your Website With Emacs and Org Mode
This howto is a translation of the original one in Spanish.
Static site generators have been quite popular for some time now as a way to create websites and most of them use Markdown as the markup language to generate the site's HTML content. Org Mode is part of many Emacs users daily routines, and once you are comfortable with it, it becomes a real pleasure to use, so why not leverage it for website content creation as well?
In this howto we will see how to use Pelican static site generator to create a website using Emacs Org Mode. This howto is not intended to cover all of Pelican's features, capabilities, or configuration options. For a complete reference, you should use the official documentation1, which is actually quite good and comprehensive.
I'm assuming you already know what Emacs and Org Mode are, and that you know how to use both. In fact, if you are reading this, chances are you are a regular Org Mode user.
Installing Pelican and Setting Up The Base Website
First step is to download and install Pelican. I do it with virtualenv but you can check out other alternatives at Pelican's website2. I open a terminal, navigate to the directory where I keep my virtual environments, and then execute the following commands:
virtualenv pelican # creates the virtual environment
source pelican/bin/activate # activates the virtual environment
pip install pelican # get and install Pelican
If you don't have virtualenv already installed, probably you can find it on your GNU/Linux distribution packages. If your system does not provide the package check out Virtualenv's official docs3.
The virtual environment stays active in this terminal session until you run
deactivate
. Don't do that yet, you still need it for the upcoming steps.
Once you have Pelican installed you should follow the quickstart steps to create the web site:
mkdir -p /local/path/to/your/website/project/folder # create a folder for your web project
cd /local/path/to/your/website/project/folder # mone inside the folder
pelican-quickstart # execute quickstart
As part of the quickstart process, Pelican will prompt you with a set of questions to configure your website project. The answers will vary depending on your needs, but here are the prompts with sample responses to guide you:
> Where do you want to create your new web site? [.]
> What will be the title of this web site? My Web Site
> Who will be the author of this web site? myself
> What will be the default language of this web site? [en]
> Do you want to specify a URL prefix? e.g., https://example.com (Y/n) Y
> What is your URL prefix? (see above example; no trailing slash) https://mysite.com
> Do you want to enable article pagination? (Y/n) Y
> How many articles per page do you want? [10]
> What is your time zone? [Europe/Rome]
> Do you want to generate a tasks.py/Makefile to automate generation and publishing? (Y/n) Y
> Do you want to upload your website using FTP? (y/N) N
> Do you want to upload your website using SSH? (y/N) y
> What is the hostname of your SSH server? [localhost]
> What is the port of your SSH server? [22]
> What is your username on that server? [root] user
> Where do you want to put your web site on that server? [/var/www]
> Do you want to upload your website using Dropbox? (y/N) N
> Do you want to upload your website using S3? (y/N) N
> Do you want to upload your website using Rackspace Cloud Files? (y/N) N
> Do you want to upload your website using GitHub Pages? (y/N) N
At this point, you can execute deactivate
on the terminal to leave the virtual
environment, we have a few things to take care of before we need it again.
Setting Up Pelican for Org Mode
To accomplish our goal we will need the org_reader plugin4. Let's get Pelican's plugins. The quickest way to get the plugins is by cloning the GitHub repo5 and put them inside a folder. Navigate to the folder where you want to store the plugins and clone the repo:
cd /path/to/folder/where/plugins/will/be/stored
git clone --recursive https://github.com/getpelican/pelican-plugins
Now open the file pelicanconf.py and add the following right at the beginning:
import os # this line shold be already inside the file
PLUGIN_PATHS = ["/path/to/pelican/plugins/folder"]
PLUGINS = ["org_reader"]
If you have an Emacs installation in a non-standard location, add the following line:
ORG_READER_EMACS_LOCATION = "/path/to/emacs/bin/emacs"
Adding Syntax Highlighting
One thing I was missing on my website was syntax highlighting for posts with source code like this one. After a bit of searching, I found Anten Linevich's site6, where he fixed it by creating a custom export backend. In order to do this let's open pelicanconf.py again and add the following:
ORG_READER_EMACS_SETTINGS = os.path.abspath("lisp/pelican-html.el")
ORG_READER_BACKEND = "'pelican-html"
Now you should create the custom export backend pelican-html. Just follow these steps:
- Add inside your site's root folder a new folder named lisp/. You can name the folder whathever you want but the name has to match the path defined on ORG_READER_EMACS_SETTINGS.
Inside the lisp/ folder, add a file named pelican-html.el and put the following inside it:
;; This code is (c) 2017 Anten Linevich and is released under ;; Creative Commons Attribution 4.0 Internacional License ;; https://linevi.ch/en/org-pygments.html (require 'org) (require 'ox) (require 'ox-html) (org-export-define-derived-backend 'pelican-html 'html :translate-alist '((src-block . pelican/pygments-org-html-code) (example-block . pelican/pygments-org-html-code))) (defvar pygments-path "pygmentize") (defun pelican/pygments-org-html-code (code contents info) "Process code block with Pygments See http://pygments.org/ for details" ;; Generate temp file path by hashing current time and date. (setq temp-source-file( format "/tmp/pygmentize-%s.txt"(md5 (current-time-string))) ) ;; Writing temp file (with-temp-file temp-source-file (insert (org-element-property :value code))) ;; Processing (shell-command-to-string (format "%s -l \"%s\" -f html %s" pygments-path (or (org-element-property :language code) "") temp-source-file))) (provide 'pelican-html)
- Save the file and syntax highlighting will be ready to go.
Writing Your First Post
Let's write a first post in order to see a basic template you can reuse when writing new posts.
There are a lot of properties (metadata in Pelican's jargon) which you can use to set up a post. Here I'm only including the ones I consider most common and/or important. You can check out Pelican's and org_reader's docs (see footnotes) to get the full list.
Inside the content/ folder of your Pelican website create a file hello-world.org with the following content:
#+TITLE: Hello World!
#+DATE: 2024-05-24
#+AUTHOR: admin
#+LANGUAGE: en
#+CATEGORY: Programming
#+PROPERTY: LANGUAGE en
#+PROPERTY: SLUG hello-world
#+PROPERTY: SUMMARY This is the post summary
#+PROPERTY: SUMMARY+ and it can have multiple lines
#+PROPERTY: TAGS programming, clang
Next we will see Hello World source code in C.
#+BEGIN_SRC c
#include <stdio.h>
int main(void)
{
printf("Hello World!");
return 0;
}
#+END_SRC
#+BEGIN_EXPORT html
<hr>
<center><small>
And this is a HTML block.
<p>
<a href="https://creativecommons.org/licenses/by-nd/4.0/">Creative Commons Attribution-NoDerivs 4.0 International (CC BY-ND 4.0)</a>
</p></small>
</center>
<hr>
#+END_EXPORT
Let's see the meaning of all these properties:
- #+TITLE: Hello World! this is the only mandatory property.
- #+DATE: 2024-05-24 the date of the document. It could be an iso format date or an Org Mode timestamp.
- #+AUTHOR: admin author name
- #+LANGUAGE: en document language for Org Mode
- #+CATEGORY: Programación post category
- #+PROPERTY: LANGUAGE es document language for Pelican
- #+PROPERTY: SLUG hello-world if you don't use this property, Pelican will use file_name.org
- #+PROPERTY: SUMMARY post summary
- #+PROPERTY: TAGS programming, clang all the tags you want to use
Apart from the properties shown in the example, there is one I find essential: #+PROPERTY: STATUS. This property can have the following values:
- published: this is the default status
- draft: post will be stored inside the drafts/ folder, inside the website, and it will not be linked anywhere.
- hidden: post is not linked anywhere, so you should know the exact URL to get to it.
Therefore, if you want to have a hidden post, you should add this property:
#+PROPERTY: STATUS hidden
Previewing and Publishing Your Website
The moment of truth has arrived, time to see the results of all the work you have done, check that everything works, and find out how to generate and publish your new website
From inside your site's root folder follow these steps:
Activate the virtual environment
source /path/to/pelican/virtualenv/bin/activate
Start the site preview in your local system by running:
make devserver
If you look closely, the previous command will return, among other things, the following:
Serving site at: http://127.0.0.1:8000 - Tap CTRL-C to stop
Copy & paste the url
http://127.0.0.1:8000
in your favourite web browser in order to see your website. The devserver mode automatically rebuilds the website whenever changes are saved in the *.org file, allowing you to view the updates instantly by refreshing the browser.You can quit the devserver mode by pressing the keys CTRL-C. Now you can publish your website by running:
make rsync_upload
Executing this command will rebuild the whole site and deploy it to the destination configured during the quickstart setup. If this doesn't work or isn't available, open the Makefile located in the root directory of your website, where you will find all the possible deployment options (ssh_upload, sftp_upload,…).
Next Steps
This howto has introduced the basics of creating a website using Pelican and managing content with Emacs and Org Mode. The next step is to explore Pelican in more depth to customize your site. Consult the Pelican documentation, choose a theme7 you like, or make a custom one.
Acknowledgements
I want to thank BxCx from #emacs-es channel on Libera.chat8 because the idea for this howto originated when he started talking about creating a static site with Emacs, and he asked me about how I built my site.
I want to thank Anten Linevich because without his post I wouldn't have figured out how to enable syntax highlighting.
Copyright
This howto is Copyright © 2024-2025 Lucio F. Albenga and is released under the terms of the Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0).
Source code of pelican-html.el file is Copyright © 2017-2024 Anten Linevich Creative Commons Attribution 4.0 International (CC BY 4.0)