An Introduction to pslssg

pslssg is the Python Standard Library Static Site Generator and is the program that builds the sauerTek website. In this post, I'll talk a little about how it works and why I made it.

What Is a Static Site Generator

In traditional blog software, you have a script that takes a blog post ID as an input, pulls content from a RDMS, and populates an HTML template before serving it back to the user as output. A static site generator is a tool that pre-generates web pages into static HTML files, which are then all uploaded and served from a traditional webserver. The advantages to static sites, for me, are:

  • No need to fuss with configuring and maintaining a RDMS.
  • Configuration management is easier; no secrets, web app config, updates, etc.
  • Better performance: pre-generating pages and serving statically is better performance for the end user.
  • Easier editing: I can write content in my editor and not in-browser.

There is really only one major downside:

  • Queries against a database need to be pre-generated. For example, "show posts with the tag 'projects'" is a simple DB query for a traditional web app, but in a static site, you need to pre-generate pages that contain links to all of the posts with that tag.

What is pslssg

pslssg is a static site generator that was built without any libraries not found in the Python standard library. In other words, pslssg does not require any pip packages to be installed. I did this for a few reasons:

  • To demonstrate the power of the Python standard library and show it off to the CincyPy Python meetup group.
  • As a fun challenge in overcoming constraints; I often find I get the most creative when constraints are enforced.
  • More generally, I made my own static site generator because I wanted to make some home cooked software. I am hoping to keep this blog going for a long time, so having the ability to fully understand and customize every line of code is beneficial.

Because of the constraints of using only the standard library, there are some interesting design decisions.

How It Works

When you start a pslssg project, you first run pslssg init which creates a few folders for you, the most important being:

  • pages - where you put XML files that will become core pages of the website
  • posts - where you put XML files that will become your blog content
  • templates - where you put XHTML files that serve as templates
  • static - where you put javascript, CSS, images, and fonts

Pages and Posts

Pages and posts are both XML files that have a specific format. They look something like this:


<?xml version="1.0"?>
<post>
  <meta>
    <template name="post.xhtml" />
    <tag name="pslssg" />
    <tag name="blog" />
    <tag name="projects" />
    <title>An Introduction to pslssg</title>
    <summary>pslssg is the "Python standard library static site generator" and is the program that builds the sauerTek website.</summary>
  </meta>
  <content>
    <p>Here is the page content you are reading now!</p>
  </content>
</post>

Each one of these XML files represents content for the website, either a core web page or a blog post. They are XML because I decided it was the easiest format to edit, over JSON, TOML, or pure Python. You can see that content has a metadata section and a content section. Metadata holds information about the post, and the content is what is inserted into the template.

Templates

Templates are XHTML files. XHTML was chosen because it is an XML compliant version of HTML, so the conversion was easy. Templates look like this:


  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>sauerTek</title>

    
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="/static/css/normalize.css" type="text/css" />
    <link rel="stylesheet" href="/static/css/skeleton.css" type="text/css" />
    <link rel="stylesheet" href="/static/css/main.css" type="text/css" />
    <link rel="icon" type="image/png" href="/static/img/favicon.ico" />

    
    
  </head>
  <body>
    <div class="container-wrapper">
      <div class="container">
        <pslssg-include template="header.xhtml" />
        <pslssg-include template="nav.xhtml" />
      </div>
    </div>
    <div class="container">
      <div class="spacer"></div>
      <pslssg-content />
    </div>
    <div class="container-wrapper dark">
      <div class="container">
        <pslssg-include template="footer.xhtml" />
      </div>
    </div>
  </body>
  
  </html>

Templates are XHTML files with a few special tags; this template has <pslssg-content /> which denotes where pslssg should place the <content> tag from the XML file. This template also has a <pslssg-include template="header.xhtml" /> tag, which inserts another template file into this one. Templates can also do inheritance, but that's outside of the scope of this post.

After the content is inserted into the template, the resulting file is written out to the build folder, which can be uploaded as an entire site.

Other Features

pslssg is supposed to have similar features to Jekyll, another static site generator. It can do things like insert metadata into posts themselves with variables, query the post database to generate lists of posts, and pre-generate tag pages. The README in the project repo has a full list of features and functionality.

List of Modules Used in pslssg

Here is a list of all of the modules pslssg uses:

  • argparse
  • os
  • logging
  • shutil
  • xml.dom.minidom
  • xml
  • sys
  • http.server
  • socketserver
  • sqlite3
  • pdb
  • unittest
  • tempfile
  • importlib.metadata
  • datetime
  • email

Future

pslssg, so far, has been pretty enjoyable to use. I'm still finding bugs and necessary features as a build out this website. I want pslssg to have more complex features, like:

  • Fetching content from a remote server (using urllib). This would be handy for dynamically pulling content from project git repos, like READMEs, reports, and version numbers.
  • A full quality suite. I wanted to get the website online, so the quality work is very lacking. I figure pslssg will be a good testbed for various quality experiments, and since the website is online, at least I can write about it!
  • More build tools, like link checking and spellcheck.

If you want to learn more, head on over to the repository listed on the project page to see the code and README!