sblg is a utility for creating static blogs. It merges articles into templates to generate static HTML files, Atom feeds, and JSON files. It's built for use with make. No PHP, no database: just a simple UNIX tool for pulling data from articles and populating templates.

How does it work? You write your HTML (really XHTML) articles and templates. sblg pulls data from the articles and merges it into the templates. This is usually orchestrated with a Makefile. And that's it. You can write articles in any format — like Markdown — so long it converts into XHTML.

To get started, check if sblg is part of your system's package manager. If it's not, download sblg.tar.gz (SHA512), decompress, run ./configure, optionally make regress and make valgrind if valgrind is installed (you should also have jq installed), then make install.

The current version is 0.6.0, released on . sblg is an open source ISO C utility that depends only on libexpat. It is a BSD.lv project and runs on OpenBSD, NetBSD, FreeBSD, Mac OS X, Linux, Solaris, and IllumOS.

latest version

: version 0.6.0

Improve interface for blog templates (all existing functionality is retained). Foremost, elements no longer need to be <nav> or <article> to trigger querying for navigation or article template blocks (data-sblg-nav and data-sblg-article, respectively).

Similarly, article sources and standalone templates no longer require <article> elements to trigger scanning for article content: the data-sblg-article attribute suffices.

Introduce data-sblg-navstyle-content and data-sblg-navstyle-element, which allow for several different ways of formatting the navigation content. The old data-sblg-navcontent and data-sblg-navxml are deprecated, but will not ever be removed.

The latest versions above are produced in a data-sblg-nav="1" element limited to one article with the version navigation tag. The version history, generated from version.xml source, has each version within an <article> with this tag, so the newest appears as shown in the index.xml source.

faq

The FAQ consists of articles with the navigation tag howto formatted with sblg then passed into a data-sblg-nav="1" element in the index.xml source. The Markdown file is translated into XML in the Makefile.

output modes

There are three basic ways of populating templates: standalone mode, which pastes a single article into a template; blog mode, which pastes multiple articles—like a blog front page; and combined, which does both. Blog mode can merge entire articles as well as just article snippets and metadata for navigation and summary purposes. (That's what this page does with its version notes.) You can also do specialty modes of Atom and JSON feeds—also part of this page.

The following templates illustrate blog and combined and combined modes. These are also used in the templates installed with the system, all of which are responsive, have feeds, etc.

Simple page-per-article template.
Simple front-page template.
Retro front-page style and Markdown.
Brutalist front-page style and Markdown.
Columnar photo blog directly from EXIF data.
Gridded photo blog directly from EXIF data.

output modes: standalone mode

standalone mode graph

Articles are just content within the <article data-sblg-article="1"> tag of an HTML (or really XML) document. sblg pulls articles and article metadata for populating navigation elements and article elements in the templates. Some important values, such as the document title, are extracted and may be filled in to the template. You can also set custom variables, such as foo in the following example article.

<?xml version="1.0" encoding="utf-8"?>
<article data-sblg-article="1">
  <header data-sblg-set-foo="bar">
    <h1>Document Title</h1>
    <address>Author Name</address>
    <time datetime="2014-04-12">2014-04-12</time>
  </header>
  <aside>
    This is pulled out for the page synopsis.
  </aside>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit,
    sed do eiusmod tempor incididunt ut labore et dolore magna
    aliqua.
  </p>
</article>

You'll also need a template. For standalone mode, this is just a regular HTML file where the <article data-sblg-article="1"> tag is replaced by the page contents.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>${sblg-titletext}</title>
    <style>
      body {width:100%; max-width: 50rem; margin: 0 auto;}
    </style>
  </head>
  <body class="${sblg-get|foo}">
    <article data-sblg-article="1"></article>
  </body>
</html>

There are all sorts of things documented in sblg that templates can fill in as extracted from article text. In the above example, a variable is used in the <title> element and expands to the title in the source <h1> element.

% sblg -o example1.html -t template.xml -c example.xml

This works well for putting simple documents into a template. But what if we want to have these documents relate to each other, or have a single document relate to multiple articles? That's where blog mode comes into play.

output modes: blog mode

blog mode graph

Blog mode is similar to standalone; however, you can also specify <nav data-sblg-nav="1"> to fill in meta-data from all articles passed into the command. And unlike in standalone mode, you can't willy-nilly use ${sblg-title} variables in the global template scope, as it's not clear to which article they'd refer. The <article> elements will be filled in with articles — as many as you stipulate — there, as in the navigation, you can use the ${sblg-title} for the currently-printed article.

<!DOCTYPE html>
<html lang="en">
  <head><title>My Blarg</title></head>
  <body>
    <nav data-sblg-nav="1"></nav>
    <article data-sblg-article="1"></article>
    <article data-sblg-article="1"></article>
  </body>
</html>

A Makefile makes this easy. Simply let individual HTML articles be built with -c from a template and source XML. Then let the main blog page be built from all source XML and a different template.

% sblg -o example2.html -t template.xml example1.xml example2.xml

In most blogs, however, one wants both a main blogroll page and each article to have navigation to other articles. The latter is accomplished with combined mode, where individual articles may also have navigation to all others.

output modes: combined mode

combined mode graph

A common usage is to mix up standalone and blog mode, where each article has its own page, and each page refers to all other pages. This can be effected using combined mode (-C), which specifies a single article for display (like with standalone mode) but may reference multiple other articles in navigation.

<!DOCTYPE html>
<html lang="en">
  <head><title>Blarg page: ${sblg-titletext}</title></head>
  <body>
    <nav data-sblg-nav="1"></nav>
    <article data-sblg-article="1"></article>
  </body>
</html>

Combined mode works well with blog mode: combined for individual articles, blog for for landing page.

% sblg -o example3.html -t template.xml -C article1.xml article1.xml article2.xml

For larger numbers of pages in combined mode, the cost of recompiling for each output can be quite high. So there's also a mode (-L) for producing one output for each input, given all inputs. These uses the default suffix mapping of replacing .xml with .html in the output.

output modes: json/atom mode

JSON/Atom mode graph

To export all articles into a JSON file or Atom feed, use their -j or -a flags, respectively. The JSON file is documented with a JSON schema distributed with the system. A TypeScript definition of the exported type is also available on npm as the sblg package. Use npm i sblg --save-dev to interface your TypeScript with a sblg blog.

contributing

There are many ways to contribute to sblg, especially if you have a specific usage case you'd like to see supported. The easiest is just to fork the repository on github, add your feature, and make a pull request. If you're looking for smaller ways to help, grep for TODO, FIXME, or even XXX in the code for missing bits. Lastly, the test coverage can certainly be improved by adding tests:

To improve these numbers, new tests may be written in the regression directory that exercise the file whose coverage you'd like to increase. Please e-mail me or contact me on GitHub for details.