Flexible static-content generation.

Blot is the static-content generator I created to build this website!

Most generators work the same way

  • Place some input content in certain specific places
  • Derive "pages", "tags", "posts" assets from content metadata
  • Use assets to drive the creation of output content

Typically, it's on you to organize your content in a way prescribed by a given generator. Metadata extracted from your content is used to derive various built-in metaphors like Pages, Tags, Posts and so on. These are then used to drive

Blot is a Programmable Content Pipeline

  • Organize your content anyway you want
  • Derive whatever asset types from your metadata you need
  • Use assets to drive the creation of output content

Many modern generators are quite flexible, most even allowing for the generation of aggregated asset types like categories and tags. However with Blot, there really is no limit to what is possible. Content goes in. Content comes out. You explain how it happens.

A small taste

Here is a Blot pipeline that builds two asset types:

# ... omitted code

minify = True

@task
def static(_):
    blot.run(context, {
        'styles': [
            DiskLoader("theme/static/less/site.less"),
            LessCompiler(),
            Conditional(lambda: minify, CSSMinify()),
            DiskTarget("site.css"),
        ],
        'scripts': [
            DiskLoader("theme/static/js/{filename}.js"),
            Concatenate(),
            Conditional(lambda: minify, JSMinify()),
            DiskTarget("site.js"),
        ]
    })
    blot.write(context)

There are two pipelines defined, styles and scripts which each conclude with the writing of a single file site.css and site.js respectively. Take a look at the styles pipeline:

        'styles': [
            DiskLoader("theme/static/less/site.less"),
            LessCompiler(),
            Conditional(lambda: minify, CSSMinify()),
            DiskTarget("site.css"),
        ]

The styles pipeline

Conceptually the styles pipeline does the following:

  • find a single file located at theme/static/less/site.less
  • compile the content as LESS to CSS
  • if minify is True, minify the content
  • target the asset for output to site.css

Then the following blot.write() call performs writing on any targetted assets in any pipeline.

The scripts pipeline

Now let's take a look at the scripts pipeline:

        'scripts': [
            DiskLoader("theme/static/js/{filename}.js"),
            Concatenate(),
            Conditional(lambda: minify, JSMinify()),
            DiskTarget("site.js"),
        ]

Notice that there is a format specifier in the argument to DiskLoader this time. In this case, multiple assets are potentially loaded, any with a filename that can be matched against the pattern. For each file, the part where the pattern appears is extracted as metadata attribute on the associated asset.

Say you have theme/static/js/foo.js, theme/static/js/bar.js and theme/static/js/extra/baz.js. Two assets will be read in each with a filename attribute set to foo and bar. On the other hand, theme/static/js/extra/baz.js is not loaded since it doesn't match. There is another way to use asterisks to match all three but I wont cover that here.

Anyway following from there, assets in the pipeline are merged into a single asset with all the content concatenated together. If minify is True, the JS is minified. Then finally, written to disk.

This is of course just a simple example of processing static web assets. When it comes to your actual site content things can get more involved. But Blot can do everything you're used to like Pages, Posts, and taxonomies like Categories and Tags and more. And you're not restricted to how you organize your content or where metadata comes from.

screenshot