Updated: 2023-04-16 Sun 13:47

Setting up this Website with Emacs Org-mode

The HTML files which make up this site were automatically generated by EMACS Org-Mode's publishing function. As a total beginner with Emacs I wanted to share my struggle creating this website so other people - maybe you - can learn from my mistakes.

Why use ORG-Mode?

Today there are a lot of (easy) ways getting your Website online. So why choose writing it in EMACS over using Wordpress for Example? My reasons at least are:

  • Browser-Editors are overkill: Wordpress and all the other are good and mighty tools. But I just want a little place in the www where I can put my writing and be found by others. I don't need forms, comment-sectins, fancy animations, selling-capability and so on. Org-Mode is perfect for a simple, text-focused website as EMACS is in its heart a text editor.
  • Cheap: Currently, I don't pay anything for this website. Not for the building-part and not for the hosting part.
  • Easy (kind of): The set up takes a few hours, but now I don't have to write any HTML or CSS when modifying or extending the site. I do everything form EMACS.
  • Fun: It's just fun exploring the capabilities of EMACS org-mode and simultaously writing for my website.

Basic setup

I use doom EMACS (v28.2) and Org mode v9.5.5. If you have never heard about EMACS or Org, you can think of EMACS as the editor and org as a kind of markup language. Org has a integrated publishing package, ox-pubish. After generating the HTML files with ox-publish into a designated website directory, I commit the changes to my remote Github repository where they automatically get posted online through Github pages.

editor doom EMACS
markup language org-mode
syncing git
hosting Github (pages)

Website-directory
  |
  |-- content_dir
  |   |-- index.org     <-- homepage org-file, gets translated to html
  |   |-- style.css
  |   |-- img_dir
  |   |-- posts_dir     <-- directory with all posts
  |
  |-- public_dir        <-- hosts the published html-files
  |-- build-site.el     <-- publishing configuration
  |-- build.sh          <-- shell script to execute build-site.el

Publishing configuration

The following code is from the publishing file 'build-site.el', which contains all the necessary publishing instuction for org publish and enables also system independant publishing as it specifies all needed packages and downloads them if not already done.

(require 'package)
(setq package-user-dir (expand-file-name "./.packages"))
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
                         ("elpa" . "https://elpa.gnu.org/packages/")))

;; Initialize the package system
(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))

;; Install dependencies
(package-install 'htmlize)

;; Load the publishing system
(require 'ox-publish)


(setq org-html-validation-link nil            ;; Don't show validation link
      org-src-fontify-natively t              ;; for code snippets
      org-html-head-include-scripts nil       ;; Use our own scripts
      org-html-head-include-default-style nil ;; Use our own styles
      org-html-doctype "html5"                ;; Use html5
      org-html-html5-fancy t                  ;; make it fancy looking
      org-export-allow-bind-keywords t)       ;; so you can use '#+incluse I think'


;; Define the publishing project
(setq org-publish-project-alist
      (list
       (list "index"
             :recursive nil
             :base-directory "./content"
             :base-extension "org"
             :publishing-function 'org-html-publish-to-html
             :publishing-directory "./public"
             :with-author nil           ;; Don't include author name
             :with-creator t            ;; Include Emacs and Org versions in footer
             :with-toc nil                ;; Include a table of contents
             :section-numbers nil       ;; Don't include section numbersi
             :html-head "<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\"/> <link rel=\"icon\" href=\"favicon.png\" type=\"image/x-icon\"/>"
             :html-preamble "<div id=\"updated\">Updated: %C</div>"
             :time-stamp-file nil)
       (list "blog"
             :recursive nil
             :base-directory "./content/blog"
             :base-extension "org"
             :publishing-function 'org-html-publish-to-html
             :publishing-directory "./public/blog"
             :with-author nil           ;; Don't include author name
             :with-creator t            ;; Include Emacs and Org versions in footer
             :with-toc nil                ;; Include a table of contents
             :section-numbers nil       ;; Don't include section numbers
             :html-head "<link rel=\"stylesheet\" href=\"../style.css\" type=\"text/css\"/> <link rel=\"icon\" href=\"../favicon.png\" type=\"image/x-icon\"/>"
             :html-preamble  "<nav>
  <a href=\"../index.html\">&lt; Home</a>
</nav>
<div id=\"updated\">Updated: %C</div>"
             :time-stamp-file nil
             :auto-sitemap t
             :sitemap-title "Blog"
             :sitemap-filename "blog.org"
             :sitemap-sort-files 'anti-chronologically)
       (list "static"
             :recursive t
             :base-directory "./content"
             :base-extension "css\\|txt\\|pdf\\|jpg\\|jpeg\\|gif\\|png"
             :publishing-function 'org-publish-attachment
             :publishing-directory "./public")))    ;; Don't include time stamp in file


;; Generate the site output
(org-publish-all t)

(message "Build complete!")
;;; build-site.el ends here

Then I run the file with the shell script 'build.sh' which I copied 1:1 from SystemCrafters, see the sources for visiting his excellent website. The created html-files are saved in the 'public' folder. I then just manually push the directory onto github where 'public' is used as root directory for this page. If you want to do the same, I agein direct you to the excellent guide form SystemCrafters.net.

Sources

Date: 2023-03-07 Tue 00:00

Emacs 28.2 (Org mode 9.5.5)