Asgardian's Blog

Migration to Weblorg.


A couple of weeks ago, I decide to start a new blog. Like I don't need something dynamic, I decide to use a static blog engine. Python is my favorit programming language, I have chosen Pelican because you can find lots of plugins and themes. To write a post, Pelican use by default Markdown but I prefer Org-Mode. So I install a specific plugin.

Why am I quitting Pelican ?

Where the list of categories was created when generating the site. Why am I quitting Pelican? Much of the articles will contain sample code. To make this code easier to read and understand, I like to use the hightlightning syntax. Under Pelican it didn't work. Pelican is very complete and easy to set up, but on the other hand, its customization requires a little more reading.

Why did I choose Weblorg ?

I'm using Emacs and Org-Mode to write my posts. Weblog is closely integrated this technologies. It's normal to use a program written in elisp to publish the site.

A better integration with Org-Mode.

The posts are written in Org-Mode so what you see is what you get including the systax hightlightning.

Easy to use and customize.

The sample site is very basic but It's very simple to customize the temmplates and CSS. Of course this requires some knowledge of web development. But it is not an insurmountable mission, depending on the result you want, you can use the most suitable technologies.

What will change ?

A publication script must be written in elisp. A local webserver must be installed. I choose an nginx server in a podman container. If you have podman on your computer, you can use this command.

podman run -it --rm -d -p 8000:80\ --name Blog\
-v /home/backfromhell/src/\

The look.

For the look, I was inspired by the Pelican-Kiera theme while combining sobriety and attractiveness to highlight the content.

The creation of a blog entry.

The header of the 2 article templates is slightly different, as well as the directory where they are stored. This will lead to modifications in the code of this part.

The generation of the site.

To generate the site, I made a program in elisp. The latter allows you to create a local site for testing and a site that will be copied to the production web server.

My publishing script is.

;;; publish.el ---  Generate a simple static HTML blog -*- lexical-binding: t -*-
;;; Commentary:
;;    Define the routes of the static website.  Each of which
;;    containing the pattern for finding Org-Mode files, which HTML
;;    template to be used, as well as their output path and URL.

;; Copyright (C) 2022 Thierry Leurent

;; Author: Thierry Leurent <>
;; Maintainer:

;; Created: 25/11/2022 01:56:17
;; Changed: 01/12/2022 00:26:23

;; Keywords: emacs

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <>.

;;; Commentary:


;;; Code:

;;| Guarantee the freshest version of the weblorg
(add-to-list 'load-path "../../")
;;| Also support loading weblorg form /opt/weblorg. This is for use with the nanzhong/weblorg image.
;;| See the volume mount in the Makefile for more context.
(add-to-list 'load-path "/opt/weblorg")

;;| Setup package management
(require 'package)
(add-to-list 'package-archives '("melpa" . "") t)
(unless (package-installed-p 'use-package)
  (package-install 'use-package))

;;| Install and configure dependencies
(use-package templatel :ensure t)
(use-package htmlize
  :ensure t
  (setq org-html-htmlize-output-type 'css))

(use-package f :ensure t)

(require 'weblorg)

(defun weblorg-custom-themes-dir ()
  "Return path to custom theme."
  (concat default-directory "themes/"))

(defun weblorg-theme-asgardian ()
  "Return path to asgardian theme."
  (concat (weblorg-custom-themes-dir) "asgardian"))

(defun create_copy_directory (source destination)
  "Copy directory and create destination if don't exist."
  (unless (file-exists-p destination)
    (make-directory destination)
  (dolist (element (directory-files source))
    (if (file-regular-p (concat source element))
        (copy-file (concat source element)
                   (concat destination element) t)
;;| base-url, for links accross the site (convenience function for
;;| deployment and local developement)
;;| in
;;| gitlab-ci.yml, can run =ENV=prod emacs --script publish.el=
(if (string= (getenv "ENV") "prod")
    (setq weblorg-default-url ""
          weblorg-output-dir "publish"
          template-var '(("site_url" . "")))
  (setq weblorg-default-url "http://localhost:8000"
        weblorg-output-dir "output"
        template-var '(("site_url" . "http://localhost:8000"))))

(setq blog-root-dir default-directory)
(setq blog-source-dir (concat blog-root-dir "content/"))
(setq blog-output-dir (concat blog-root-dir weblorg-output-dir "/"))

(setq template-vars '(("site_name" . "Asgardian's Blog")
                      ("site_owner" . "BackFromHell")
                      ("site_description" . "Animated by passion.")
                      ("site_keywords" . "Emacs, Python, Beer, Brewery, Electronic.")
                      ("default_lang" . "en_US")
                      ("favicon" . "extra/favicon.ico")
                      ("social_medias" . ((("url" . "")
                                           ("name" . "gitlab"))
                                          (("url" . "")
                                           ("name" . "mastodon"))
                      ("atom" . "")


;;| Set site wide configuration
 :base-url weblorg-default-url
 :theme #'weblorg-theme-asgardian
 :template-vars (append template-var template-vars)

;;| Delete output folder.
(f-delete "output/*" t)

;;| Generate blog posts
 :name "posts"
 :input-pattern "content/posts/*.org"
 :template "post.html"
 :output (concat weblorg-output-dir "/posts/{{ slug }}.html")
 :url "/posts/{{ slug }}.html")

;;| Generate pages
 :name "pages"
 :input-pattern "content/pages/*.org"
 :template "page.html"
 :output (concat weblorg-output-dir "/{{ slug }}/index.html")
 :url "/{{ slug }}")

;;| Generate posts summary
 :name "index"
 :input-pattern "content/posts/*.org"
 :input-aggregate #'weblorg-input-aggregate-all-desc
 :template "blog.html"
 :output (concat weblorg-output-dir "/index.html")
 :url "/")

 :name "feed"
 :input-pattern "content/posts/*.org"
 :input-aggregate #'weblorg-input-aggregate-all-desc
 :template "feed.xml"
 :output (concat weblorg-output-dir "/feed.xml")
 :url "/feed.xml")

 :name "categories"
 :input-pattern "content/posts/*.org"
 :input-aggregate #'weblorg-input-aggregate-by-category-desc
 :template "category.html"
 :output (concat weblorg-output-dir "/categories/{{ name }}/index.html")
 :url (concat "/" weblorg-output-dir "/categories/{{ name }}"))

 :output (concat weblorg-output-dir "/static/{{ file }}")
 :url "/static/{{ file }}")


;;| Create Blog-extra-output-folder if do not exist.
(create_copy_directory (concat blog-source-dir "extra/")
                       (concat blog-output-dir "extra/"))

;;| Create Blog-images-output-folder if do not exist.
(create_copy_directory (concat blog-source-dir "posts/images/")
                       (concat blog-output-dir "posts/images/"))

;;; publish.el ends here

To generate the testing site, uses this commands.

cd /weblorg_directory 
emacs --script ./publish.el

To generate the production site, uses this commands.

export ENV=prod
cd /weblorg_directory 
emacs --script ./publish.el