, 7 min read

Example Theme for Simplified Saaze: Paternoster

Original post is here eklausmeier.goip.de/blog/2023/06-23-example-theme-for-simplified-saaze-paternoster.

1. Features. Here is another theme called Paternoster for Simplified Saaze. The example content is from Leon Paternoster.

Some key features:

  1. Multiblog: 3 different blog types, i.e., one classical blog, one Twitter like blog, one link-collection blog
  2. Lightweight as there are no gimmicks, no social media icons, no categories+tags, no dark theme switcher
  3. Fully responsive with media breaks at 20em, 40em, 100em, and an extra one for paper-print.
  4. Easy to amend a commenting system, see for example HashOver.

This theme is the seventh example theme. We had themes migrated from WordPress, from Hugo, now a migration from Jekyll.

2. Migration from Jekyll. Leon Paternoster used Jekyll as static site generator. Furthermore, he kept all his Markdown files in GitHub. Getting the content and styles was therefore easy.

For converting Jekyll to Simplified Saaze I used Perl script blogleonp.

cd about
blogleonp index.md > ~/php/saaze-paternoster/content/aux/about.md
blogleonp what-is-rss/index.md > ~/php/saaze-paternoster/content/aux/what-is-rss.md
cd ../_notes
blogleonpAll . ~/php/saaze-paternoster/content/notes/
cd ../_links
time ( for i in *.md; do echo $i; blogleonp $i > ~/php/saaze-paternoster/content/links/$i; done )
cd ../_posts
blogleonpAll . ~/php/saaze-paternoster/content/posts/

Shell script blogleonpAll is:

# Run Perl script blogleonp on all Markdown files in directory $1 and write to directory $2
# Only relevant for _posts + _notes, not relevant for _links

[ -z "$1" ] && exit 1
[ -z "$2" ] && exit 2
echo "Source=$1, target=$2"

cd "$1"
for i in *.markdown *.md *.mkd; do
    fn=${i// /-}
    [[ $fn =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}- ]] && fn=${fn:11}
    [ -f "$2/$fn.md" ] && echo "duplicate: $i" && fn=${fn}2
    echo "i=$i, fn=$fn"
    blogleonp "$i" > "$2/$fn"

So, the files in about are treated specially. Markdown files in _posts must sometimes extract the date: information from the filename. The rest of the Markdown files can be processed by just running them through blogleonp. Example call:

blogleonpAll . ~/php/saaze-paternoster/content/posts/

3. Differences to original. Here is a list of stylistic changes and shortcomings.

  1. In the original there are two menus, one at the top and one at the bottom, and they are different. I harmonized them into one single menu.
  2. Added yellow blockquote to indicate that the post or note is a copy. Easy to remove in template posts/entry.php.
  3. CSS is in a separate file and no longer inlined. CSS file is 17KB, so a bit too large for inlining. I am using some "sematic HTML" tags, see Ihuoma Ndukwe .
  4. Image handling is very simplistic. The original encapsulates images in <picture> tags, I only use the standard Markdown form ![](...).
  5. The "home-page" was removed: it is just the same as the posts-index page, except that it only contains 10 entries. The "home-page" is now just a redirect to the posts-index page.
  6. Index-pages for posts, links, and notes contain 50 entries per page. After 50 entries you have to click "older" or "newer". See next difference.
  7. Search functionality is "builtin". There is no redirect to DuckDuckGo, which is mostly just Bing. Also, Bing visits many smaller blogs infrequently, therefore a user searching for content might not find it, even though it is actually present. Search is directly on HTML pages: if there is something in the blog, it will be found. Therefore it doesn't make too much sense to have huge index-pages, where you would have to use the search functionality of your browser.
  8. No "Previous" and "Next" in posts, links, and notes.
  9. Does not automatically handle {:toc} commands, i.e., generate table of contents. Though, there is a simply workaround, see Table of Contents in Saaze.
  10. The original version has some glitches when checked via Nu HTML Checker.

There would be reasons to not generate 249 index.html files for links, as they are not directly accessible. You only find them, when you specifically search for them.

4. Installation. Check your PHP version with php -v to make sure you have at least version 8. Install Composer, if you have not already done so. Then run:

composer create-project eklausme/saaze-paternoster

This will create a directory named saaze-paternoster. This contains the theme, it will also contain Simplified Saaze. Though, you also need to install the following for Simplified Saaze:

  1. PHP Yaml extension, e.g., via trizen php-yaml
  2. Compile php_md4c_toHtml.c

See Installation. For MS Windows specific installation instructions see Installing Simplified Saaze on Windows 10 and Installing Simplified Saaze on Windows 10 #2.

6. Generating HTML and RSS. Once everything is installed, change to the directory and run Simplified Saaze:

cd .../saaze-paternoster
php saaze -rb /tmp/build

This will create a directory called build in the /tmp directory, which contains all generated HTML files. The -b directory option is entirely optional. I only use it as on Arch Linux /tmp is a RAM disk by default.

Option -r generates RSS. Filename of RSS file is feed.xml.

Generation is quite fast:

Building static site in /tmp/build...
        execute(): filePath=/home/klm/php/saaze-paternoster/content/links.yml, nentries=249, totalPages=5, entries_per_page=50
        execute(): filePath=/home/klm/php/saaze-paternoster/content/notes.yml, nentries=470, totalPages=10, entries_per_page=50
        execute(): filePath=/home/klm/php/saaze-paternoster/content/posts.yml, nentries=210, totalPages=11, entries_per_page=20
        execute(): filePath=/home/klm/php/saaze-paternoster/content/aux.yml, nentries=3, totalPages=1, entries_per_page=20
Finished creating 4 collections, 4 with index, and 932 entries (0.09 secs / 5.88MB)
#collections=4, YamlParser=0.0097/940-4, md2html=0.0075, MathParser=0.0032/932, renderEntry=932, content=932/0, excerpt=0/0
        real 0.11s
        user 0.08s
        sys 0
        swapped 0
        total space 0

Above command generates 249+470+210+3=932 entries. According Zola experiments part 1 the static site generator Zola required 46ms for less than a quarter of the work, i.e., generating 210 entries. That's in line with the benchmarks in Performance Comparison Saaze vs. Hugo vs. Zola. According Getting charged by Netlify for the first time a Jekyll build takes 60s. That's more than 300 times more than above build including deployment, see below.

Simplified Saaze offers a dynamic mode, see Dynamic conten generation. With that the HTML page is generated at the moment a user requests it. This mode is attractive in case you blog in a Twitter-like mode, i.e., quite frequently, or making otherwise frequent changes.

7. Speed test. Testing new and old webpages on tools.pingdom.com. Test was conducted with Decorating minimalism. Test location in pingdom was Europe/Germany/Frankfurt.

Contender Grade Page size Load time Requests
S. Saaze A98 11.0 KB 113ms 4
original A98 17.3 KB 428ms 5

8. Deployment. Here is a deploy-script to actually copy all HTML files and images to a webserver directory, /srv/http/paternoster in this case. Actually, it is not a copy but a simple "move". Below script also assumes that the build directory is in /tmp/build. It can be anywhere.

# Deploy Leon Paternoster's static site on eklausmeier.goip.de


rm -rf paternoster
mv $BUILD paternoster
cd paternoster
ln -s $SAAZEROOT/public/paternoster.css
ln -s $SAAZEROOT/public/img
ln -s $SAAZEROOT/public/index.html
mkdir feed
mv feed.xml feed/index.xml

# Construct search.php from templates and raw search.php, copy to $DOCROOT/paternoster
cat	<(echo "<?php \$title=\"Search\"; \$url=\"/paternoster/aux/search.php\"; \$rbase='/paternoster'; \$cdirs=\"paternoster\"; ?>")	\
    <( perl -ne 'if (/\s+require SAAZE_PATH . "([\.\w\/]+)"/) { open(F,"<'"$SAAZEROOT"'$1");print <F>; } else { print; }' $SAAZEROOT/templates/top-layout.php )	\
    $SAAZEROOT/content/aux/search.php	\
    $SAAZEROOT/templates/bottom-layout.php	\
    > $DOCROOT/paternoster/aux/search.php

This script might use lftp or scp to copy HTML files, if your webserver is on another machine. It might contain a call to one of the many npm commands used by Vercel, Netlify, or Cloudflare, see Hosting Static Content with now.sh, or Hosting Static Content with netlify.app, or Hosting Static Content with Cloudflare. The "difficult" part in above script is to assemble the search.php file from the template files.

Deployment is quick:

~/php/saaze-paternoster: time blogleonpDeploy
        real 0.07s
        user 0.01s
        sys 0
        swapped 0
        total space 0

The blog looks something like this:

Just recently the font was changed from old-style to sans-serif. Apparently Leon Paternoster likes to play with CSS. No wonder, as his blog contains quite a lot of stuff on CSS. His remarks on "CSS Naked Day" were the starting point to comb through his blog.