Refining the look and feel of this blog

I'm sure this will be an ongoing process but getting to the point the site is at currently took quite some doing so I want to capture what I've done so far so anyone wishing to follow along can.

Git submodules need to be populated before they're useful

At first I couldn't get any theme applied. No matter what I did nothing would change the look of the output. It took an embarrassingly long amount of time to realize that the submodules I included for themes and plugins weren't populated with any content. Forgive me as I'm rather new to submodules in git. Once I found the command git submodule update --init --recursive I had what I needed.

Landing on a theme

It took a good long while to find the right theme. My idea behind this blog is to have something that's relatively professional. I want it to both look nice with a fair amount of flash without going overboard. In other words it should not be embarrassing if my employer finds it. I think I found what I'm looking for in pelican-twitchy. It needed some mods which I'll get into later and I had to adjust my workflow to accommodate pelican but it's coming together.

Fighting with code blocks

You've probably noticed I use a lot of code blocks in my blogs. That's because a lot my blog is me discussing the code that I write and use. Ideally the code blocks that show up on the blog should appear as close to possible to what I see in my text editor, Emacs. Sadly that's just not possible with the org_reader plugin for pelican. By default code blocks were displaying as a simple black box with white text. Inline code was just bold. I had hoped that applying a theme would improve things but no it made things much worse. Instead of a readable black box with white text I had a gray box with slightly darker gray text. I tried in vein to use the pelican theme to apply pygments to the code blocks. Only to discover that they would only work with markdown. Purely by chance I used org-modes export to html feature and noticed pelican processing the html. Ah Ha! Pelican has a built-in html reader. Comparing the two pages one generated by org_reader and the other generated from html I noticed the html processed page had some syntax highlighting. It was difficult to see the highlighted text in the code blocks as the colors are meant for dark mode but it was there. The primary text was now black so at least I could read it.

The code block backgrounds

I had to change the background color of the code blocks before I could see what I was doing. Comparing the org generated html with the pelican generated html the code blocks looked identical. Checking online I found several pages that claim pelican doesn't do any styling of code blocks. To my mind that must mean it's just taking the org generated html for the code blocks wholesale and passing it on. Diving into org modes export feature I eventually managed to change the background color of the exported html only to find pelican then clobbered that setting and reinforcing the gray background. So much for listening to random people on the internet. I then decided that the theme was to blame surly different color themes would use a different color style for code blocks right? After an hour or so of trying different themes only to be met with the same ugly code blocks I was ready to give up and just convert to markdown and pygments. But there had to be a way. That's when I remembered that Firefox has built-in web developer tools. That could tell me which of the style sheets were setting the code block background. After making a copy of the pelican-twitchy theme so I could make modifications without causing issues in the submodule I found the code block background value in ./pelican-twitch-mod/static/css/boostrap.lumen.min.css and set it to my preferred shade of dark blue. Great now I can see my syntax highlighting and as expected it's identical to what I see in Emacs. But the primary text color was now black. Black on dark blue is also unreadable. Thankfully the code blocks primary text color is set in the same block of css as the background. After changing it to white I could finally had the code blocks I was looking for. After changing these values in the same css file for inline code I was done. For now anyway.

Rainbow delimiters

While looking online for solutions to my various issues I came across several people discussing a incompatibility with the Emacs package rainbow-delimiters and org-mode export to html. In my testing this bug has been fixed so I enabled the package in the dev shell's Emacs lisp.

(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

Setting up the new workflow

To pelicans credit applying the theme was a simple matter of adding the corresponding attributes to the pelicanconfig.conf file. All of this was explained in the pelican-twitchy documentation. I'll probably take advantage of more of the themes features in the future but for now this is a good start.

THEME = "./pelican-twitchy-mod/"
RECENT_POST_COUNT = 5
EXPAND_LATEST_ON_INDEX = True
DISPLAY_RECENT_POSTS_ON_MENU = True
DISPLAY_CATEGORIES_ON_MENU = False
BOOTSTRAP_THEME = "lumen"
OPEN_GRAPH = True
TYPOGRIFY = False

Since I don't need two copies for every blog post I needed to disable pelicans org_reader by removing the associated line in pelicanconfig.conf.

PLUGINS = ['org_reader']

Pelican interprets the html in a very straightforward manner, reading metadata from meta tags. Refer to their documentation for the details. After manually modifying the headers of the existing org files I needed to update the custom Emacs function to produce the headers I need. Doing multiple layers of string concatenation in a single line was starting to make my head spin so I made a variable per line. Breaking up the header like that makes the function more readable I think. Here's the resulting function.

(defun sda/new-post ()
  (interactive)
  (setq new-blog-post-title (read-from-minibuffer "Post name: "))
  (setq new-blog-post-tags (read-from-minibuffer "Tags: "))
  (setq new-blog-post-slug (downcase (replace-regexp-in-string "[^[:alpha:][:digit:]_-]" "" (string-replace " " "-" new-blog-post-title))))
  (setq new-blog-post-filename-base (string-inflection-lower-camelcase-function (string-replace " " "_" new-blog-post-title)))
  (setq new-blog-post-file (concat "./content/blog/" new-blog-post-filename-base ".org"))
  (setq new-blog-title-line (concat "#+HTML_HEAD: <title>" new-blog-post-title "</title>"))
  (setq new-blog-date-line (concat "#+HTML_HEAD: <meta name=\"date\" content=\"" (format-time-string "%Y-%m-%d") "\" />"))
  (setq new-blog-slug-line (concat "#+HTML_HEAD: <meta name=\"slug\" content=\"" new-blog-post-slug "\" />"))
  (setq new-blog-keywords-line (concat "#+HTML_HEAD: <meta name=\"keywords\" content=\"" new-blog-post-tags "\" />"))
  (setq new-blog-language-line "#+HTML_HEAD: <meta name=\"language\" content=\"en\" />")
  (setq new-blog-author-line "#+AUTHOR: SpeDAllen")
  (setq new-blog-options-line "#+options: toc:nil num:nil ^:nil html-postamble:nil")
  (setq new-blog-filename-line (concat "#+EXPORT_FILE_NAME: " new-blog-post-filename-base))
  (let ((org-capture-templates
        `(("p" "New Pelican blog post" plain (file new-blog-post-file)
           ,(concat new-blog-title-line "\n" new-blog-date-line "\n" new-blog-keywords-line "\n" new-blog-slug-line "\n" new-blog-language-line "\n" new-blog-author-line "\n" new-blog-options-line "\n" new-blog-filename-line "\n\n")))
        )) (org-capture)))

Ultimately my workflow doesn't change much. I still cd into the blog git repository, run nix develop, then inside Emacs run M-x sda/new-post, and fill in the content of my new post. Only now I need to save then export that content to html before pelican will pick it up. If you're new to Emacs org-mode the default keybinding for that is C-x C-s C-c C-e h h

Final thoughts

I'm rather happy with how the site it coming along. It's strangely satisfying to see the results of all this struggle and heartache. My inexperience as a web developer is really rearing it's ugly head. Not that this blog makes me in any way a web developer. I work with people who are and they would laugh my struggles off as child's play. To me, someone who has zero experience or formal training as a web developer, this site is a minor accomplishment. So don't mind me if I take some amount of pride in it.

- SpeDAllen