sblg is a utility for creating static blogs. It knits together articles with templates to generate static HTML files, Atom feeds, and JSON files. It's built for use with make(1). 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(1) 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 as they can convert into a conforming XHTML document.)

To get started, download sblg.tar.gz (SHA512), decompress, run ./configure then make install. The current version is 0.5.6, released on . Alternatively, use the GitHub repository or your operating system's package manager (OpenBSD, Homebrew, etc.).

sblg is an open source ISO C utility that depends only on libexpat. It is a BSD.lv project.

latest version

(See all versions.)

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.

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(1) 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(1) 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 -t template.xml -c example.xml
view results

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.

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 -t template.xml example1.xml example2.xml
view results

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.

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 -t template.xml -C article1.xml article1.xml article2.xml
view results

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.