Minimal Blogging Setup with Orgmode and ssg5
Published 2020-07-21 on Anjan's Homepage
My Old Setup
I prefer orgmode over markdown because already I use orgmode for appointments, reminders, notes, etc.
However, most static website generators only support Markdown.
Luckily, orgmode has an html export function: M-x org-publish
.
org-publish is much more powerful and reliable than any markdown converter I have used.
Since 2016, I have been using jekyll which is bloated and requires a lot of ruby dependencies. To make sure my website always built, I setup sourcehut builds to build my jekyll website. Each website build takes 3 minutes on sourcehut.
Building the website locally was also a terrible experience.
I had hacked on a shell script that would take my org-publish
output and make it usable for jekyll by setting the title and layout variables.
To publish a new blog post, I had to: org-publish -> run my script -> commit html AND org file -> wait for jekyll to build on sourcehut
.
If I had made a mistake, I would repeat the entire process…
Eventually this setup was so cumbersome, I stopped blogging.
My New Setup
I do not use most of the features of jekyll and needed something more minimal. In the past, I have dabbled with werc, hugo, and guile-haunt. Eventually, I stumbled upon ssg5 which is a static site generator written in 180 lines of posix compliant shell. If you do not use markdown, ssg5 will only use unix coreutils to make your website with a common header and footer. Perfect!
I decided I should go through the pain of porting my website over to ssg5 and documenting my experience. Here is what I had to pay attention to:
Openring
To generate the “Articles from blogs I follow around the net” at the bottom of each blog post, I use openring.
Openring is a great way to support a more decentralized internet where everyone has their own website.
A template for the blog post footer is saved as webring-in.html.
My openring.sh
script downloads openring
and prints to stdout the html to be included at the end of blog posts.
Changes to rssg
To generate my rss feed, I use rssg.
However, rssg requires a list of posts on the homepage.
Unfortunately, ssg5 does not generate a list of posts and I had to hack together blogfeed.sh.
Here is the output from blogfeed.sh
:
<li>2020-07-21 <a href="/posts/2020-07-21-ssg.html" title="2020-07-21">Minimal Blogging Setup with Orgmode and ssg5</a></li> <li>2020-07-06 <a href="/posts/2020-07-06-crust.html" title="2020-07-06">Compiling crust for pinephone on Postmarketos</a></li> ... <li>2016-04-26 <a href="/posts/2016-04-26-Hello-World.html" title="2016-04-26">Hello World</a></li>
My fork of rssg is located here.
Gnu coreutils’ date command does not have a -j
flag as required by the date_rfc_822()
function in rssg.
The dates output by blogfeed.sh
are in YYYY-MM-DD format.
To convert to rfc_882
, I used the following date command in the date_rfc_822
function:
date_rfc_822() { date -R -d "$1" }
Changes to ssg5
My fork of ssg5 is located here.
I modified ssg5 to run openring, run rssg, and change the footer depending on the page.
Running openring takes alot of time which is inconvenient when editing a page locally so I implemented a -f
flag to ssg5.
If -f
is the fifth argument into ssg5, the script doesn’t generate the webring.
In the main function on line 52, I load in the “Articles from blogs I follow” html into an environmental variable called $WEBRING
:
[ "$5" != "-f" ] && WEBRING="$(./openring.sh)" && export WEBRING
On line 53, I generate the blogfeed to be included at the bottom of the homepage:
FEED="$(./blogfeed.sh)" && export FEED
Depending on whether the page is homepage or a blog post, I need to include a different footer.
If the page is a blog post, I must include the openring output and if the page is the homepage I must include the blog post log (generated by blogfeed.sh
).
As such, I changed the render_html_files()
function to:
render_html_files() { while read -r f do echo "$1/$f" | grep "index.html" > /dev/null && EXTRAFOOT="$FEED" && export EXTRAFOOT echo "$1/$f" | grep "posts" > /dev/null && EXTRAFOOT="$WEBRING" && export EXTRAFOOT render_html_file "$3" < "$1/$f" > "$2/$f" EXTRAFOOT="" && export EXTRAFOOT done }
If the file name matches the regular expression index.html
, it gets $FEED
as the extra footer.
If the file name is matches the posts regular expression, $WEBRING
is the extra footer.
Finally, I modified the render_html_file
function to include my environmental variable $EXTRAFOOT
before $FOOTER
:
... } print body print ENVIRON["EXTRAFOOT"] print ENVIRON["FOOTER"] }'
At the end of the main
function in my ssg
script, I use rssg
to generate my site’s rss feed:
[ "$5" != "-f" ] && ./rssg dst/index.html 'Anjan Momi Homepage' > dst/feed.xml
Orgmode
In my .spacemacs
, I added the following lines:
(setq org-publish-project-alist '(("momi" ;; Path to org files. :base-directory "~/code/momi.ca/src/" :base-extension "org" ;; Path to ssg osts :publishing-directory "~/code/momi.ca/src/" :recursive t :publishing-function org-html-publish-to-html :body-only t ;ssg will not add header and footer if an <HTML> tag exists :link-up /index.html :html-postamble t :toc nil )))
Open an org file from your website and run C-c C-e P p
to generate the html for your blog files.
If you edit the org-publish-project-alist
variable and want to regenerate all files (even unmodified) run:
C-u 1 M-x org-publish
.
Deployment
To simplify the deployment of my website, I added the following aliases to my zshrc:
alias makesite="rm dst/.files; ./ssg5 src dst \"Anjandev\'s Homepage\" https://momi.ca" alias deploysite="rsync -rvPz --delete dst/ deploy@homeserver:/"
In the makesite
alias, rm dst/.files
ensures ssg5 will rebuild all the website’s pages.
Conclusion
To check mistakes with my website’s rss and html, I used w3c’s validation service for html and rss.
Finally, I had to go back in time and convert all my Markdown posts to orgmode.
My website now generates in under a second for a clean build compared to 3 minutes with jekyll. I don’t have to use jekyll, jekyll’s dependencies, and sourcehut to build my website. Expect more blog posts going into the future!
Have a comment on one of my posts? Start a discussion in my public inbox by sending an email to ~anjan/public-inbox@lists.sr.ht [mailing list etiquette]
Articles from blogs I follow around the net
These articles/blogs do not represent my own opinions or views.Text processing on the Command Line - sharing my tools
Text processing on the command line - sharing my tools Introduction I'm quite fond of the command-line and spend a larger chunk of my life in a terminal emulator than I dare admit. I try to embrace the unix philosophy of using tools that "do one thing…
via Proycon's website July 7, 2024Linux phones are not automatically secure
A common point in the Linux community is that escaping the walled garden of ecosystems like Android or iOS is already a means to higher security. Having no contact with Google or Apple servers ever again, nor cloud providers ever snooping on your private …
via TuxPhones - Linux phones, tablets and portable devices January 25, 2023Generated by openring