¶Initial Build of a Minimal Site
This is the first step in building my website. Looking forward, I want to rely on typing the content of my page using Org Mode. This is a sort of markdown that comes built into Emacs that really goes far beyond a “sort of markdown” that I unfairly stated. It’s pretty awesome and has more functionality that I could begin to imagine, let along describe. I also want to be able to convert Jupyter Notebooks, but I’m going to figure that part out later. The output here will be far from a finished product, but this is a solid first step.
¶Setting Up Emacs and Org Mode Publishing
Following this guide, Build Your Website with Org Mode by SystemCrafters, it’s easy to get started. The idea here is that you write each of your site’s pages as individual Org Mode documents, and then you use Org Mode’s publishing system to convert those documents into individual HTML files in a stucture that mirrors the Org Mode content.
¶Creating the Build Site Script
We start off by building the Elisp script that we will run with base Emacs (no configuration loaded). This is built to be used anywhere by anyone with Emacs 25 or higher installed. This is important because later, we’ll use a virtual machine to run our script from scratch each time we push a commit. This section won’t be vastly different from David’s very helpful SystemCrafters video, but I want to include it because it’s where I am starting, and I’ll on from there quite a bit.
We start off our build script, build-site.el
, by loading the Org Mode publishing system, ox-publish
.
;; Load the publishing system ;; This generates the HTML output from org-mode documents (require 'ox-publish)
Next, we need to install some additional dependencies. Initially, we’ll just install htmlize
. Without it, code blocks, such as the ones on this page, do not show up with any syntax highlighting. Most posts on this site are going to have code blocks, so I definitely want to include syntax hightlighting! First though, we need to add the MELPA package repository and refresh the contents of that repository so we can install the dependencies.
;; Set the package installation directory so that packages aren't stored in ;; the ~/.emacs.d/elpa path. (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 - htmlize is needed for code syntax highlighting (package-install 'htmlize)
Now, we’ll customize some of the HTML output by changing a few variables associated with Org Mode’s publisher. When the Org documents are exported to HTML, they include a few things I don’t want on my site, such as a HTML validation link and some default JavaScript and styling. We can also point to a specific style sheet here.
Note: This is useful for now, but later, we’ll change this. These variables all impact the header and footer of the site, but later we’ll only use Org Mode to publish the body of the content and let Jekyll handle the rest of the content.
;; Customize the HTML output (setq ;; Don't add the HTML Validate link at the bottom of our published page org-html-validation-link nil ;; Don't add the default JavaScript org-html-head-include-scripts nil ;; Don't use the default styles org-html-head-include-default-style nil ;; Use a pre-built CSS org-html-head "<link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\" />")
We need to tell Org Mode what exactly we want to publish and where to publish it to. For now, the website root directory is website
, all of my Org Mode documents are in a subdirectory called base-directory
, and I want to send my exported HTML files to a subdirectory called public
. We can also handle a few other items here, such as turning off the Table of Contents, author name, and time stamp.
;; Set the project to publish upon running this script as well as how ;; to publish them (setq org-publish-project-alist (list (list "website" ;; Publish all files in the base directory :recursive t ;; Where the org-mode files are located :base-directory "./content" ;; Where the HTML files are generated :publishing-directory "./public" ;; Function to convert org-mode to desired format :publishing-function 'org-html-publish-to-html ;; Don't show the author in the footer :with-author nil ;; Add that site was generated with Emacs org-mode in footer :with-creator t ;; Don't add the table of contents :with-toc nil ;; Don't add section numbers in the headings :section-numbers nil ;; Don't include a time-stamp in the file :time-stamp-file nil)))
Finally, we’ll tell Org Mode to regenerate the entire list of projects listed above each time we run the build script.
;; Generate the site output (org-publish-all t)
And then, just as a sanity check, we’ll print a message letting us know we made it to the end.
(message "Build complete!")
¶Calling the Build Script
Lastly, we just need to call Emacs to run this script in the shell. That’s pretty quickly done in one line in a shell script, build.sh
:
emacs -Q --script build-site.el
Here, the -Q
flag tells Emacs not to load any configuration, splash screens, or anything else, and --script
tells Emacs to run the Elisp script file we specify. Next, we can make the command executable by running
chmod +x build.sh
and finally, run the shell script that runs Emacs and the build script using
./build.sh
And now, barring any errors in performing the export, all of our Org Mode documents should have been exported to HTML files in the public
subdirectory.