chronicle - A static blog-compiler.


  chronicle [options]

  Path Options:

   --comments       Specify the path to the optional comments directory.
   --config         Specify a configuration file to read.
   --database       Specify the path to the SQLite database to create/use.
   --input          Specify the input directory to use.
   --output         Specify the directory to write output to.
   --pattern        Specify the pattern of files to work with.
   --theme          Specify the theme to use.
   --theme-dir      Specify the path to the theme templates.
   --url-prefix     Specify the prefix to the generated blog.
   --template-engine Specify the template system to use
                    (HTMLTemplate (default), Xslate or XslateTT)

  Counting Options:

   --comment-days=N    The maximum age a post may allow comments.
   --entry-count=N     Number of posts to show on the index.
   --rss-count=N       Number of posts to include on the RSS index feed.

  Optional Features:

   --author        Specify the author's email address.
   --blog-subtitle Set the title of the blog.
   --blog-title    Set the title of the blog.
   --force         Always regenerate pages.
   --lower-case    Write only lower-case post-files.
                   Allow non-ASCII characters in file names. Default is
                   `no'. Use `mac' if serving files off an HFS+ volume.

  Help Options:

   --help         Show the help information for this script.
   --list-plugins List the available plugins.
   --list-themes  List the available themes.
   --manual       Read the manual for this script.
   --verbose      Show useful debugging information.
   --version      Show the version number and exit.


Chronicle is a blog-compiler which will convert a directory full of plain-text blog-posts into a fully-featured HTML website containing posts, tags, and archives.

All blog-posts from a given input directory are parsed into a SQLite database which is then used to generate the output pages.

The SQLite database is assumed to persist, such that it will be updated if new posts are written, or previous posts are updated. However if it is removed it will be recreated when needed.


When chronicle is first executed it will create an SQLite database if it is not already present. The database will contain two tables, one for the posts, and one to store the tags associated with the posts, if you choose to use tags in your entries.

The blog-entry table contains the following columns:


The mtime of the input file.


The date-header as self-reported in the blog-post.


The body of the blog-post itself.


The title of the blog-post itself.

If you wish to add extra tables via a local plugin you're welcome to do so.


The main driver, chronicle, is responsible for only a few small jobs:

Finding Blog Posts.

By default data/*.txt are read, but you may adjust the input directory via the --input command-line flag. The pattern may be set with --pattern.

NOTE The pattern is applied recursively, if you wish to create sub-directories with your posts inside them for organizational purposes.

Inserting them into the SQLite database.

The header is read to look for things such as the post-date, the subject, and the tags. The body is imported literally, unless expanded and reformatted via a plugin.

Executing plugins

Each registered plugin will be invoked in turn, allowing the various output parts to be generated.

The output is exclusively generated by the plugins bundled with the code.

For example all of the tag-pages, located beneath /tags/ in your generated site, are generated by the Chronicle::Plugin::Generate::Tags module.

The core will call the following methods if present in plugins:


This is called if the SQLite database does not exist and must be created. This method can be used to add new columns or tables to the database, etc.


This is called when an existing SQLite database is opened, and we use it to set memory/sync options.


This method is invoked as a blog entry is read to disk before it is inserted into the database for the first time - or when the item on disk has been changed and the database entry must be refreshed.

This method is the perfect place to handle format conversion, which is demonstrated in the following plugins:


Beyond format conversion this method is also good for expanding macros, or snippets of HTML. (This is done by Chronicle::Plugin::YouTube for example.)


This is called prior to any generation, with a reference to the configuration options and the database handle used for storage.


This is called to generate the output pages. There is no logical difference between this method and on_initiate except that the former plugin methods are guaranteed to have been called prior to on_generate being invoked.

Again a reference to the configuration options, and the database handle is provided.

Any plugin in the Chronicle::Plugin:: namespace will be loaded when the script starts.

You might wish to disable plugins, and this can be done via command-line flags such as --exclude-plugin=RSS,Verbose.


There is a small collection of themes bundled with the release, and it is assumed you might write your own.

Themes are located beneath a particular directory, such that the files contained in one are located at:


These two names can be set via --theme-dir and --theme respectively.

Each theme will consist of a small number of template files that use HTML::Template by default but can use other templating systems depending on the --template-engine parameter. In brief, a theme is complete if it contains:


This is the file used to generate an archived month/year index.


This is the file used to generate the top-level /archive/ page.


This is the file used to generate each individual blog-entry.


This is the file used to generate your front-page.


This is the file used to generate your RSS feed.


This is the file used to generate the top-level /tag/XX/ page.


This is the file used to generate the top-level /tag/ page.

Each theme page will receive different data, as set by the appropriate generation plugin, and any global Chronicle::Plugin::Snippets plugins which have been loaded.


There are currently three possible values for the --template-engine parameter. Each uses templates with different file extensions so you can have different sets of templates in the same directory without causing conflicts.


This is the traditional template engine and the default. Templates are named *.tmpl.


Uses Text::Xslate, an extremely fast and versatile templating system, with its default "Kolon" syntax. Templates are named *.tx.


Uses Text::Xslate with the Template Toolkit compatible "TTerse" syntax. Templates are named *.ttx.


How do I generate a new type of pages?

If you wish to generate a new hierarchy of pages then you should create a new plugin to generate them. The Chronicle::Plugin::Generate::RSS would be a good starting point.

How do I include some data in each page?

If you wish to make a piece of data available to all output pages then it must be generated first.

That is what the plugins beneath the Chronicle::Plugin::Snippets hierarchy do - They are invoked first and can update the global variables to make some new data available to all the templates.

This is how the global tag-cloud, recent posts, and similar data is able to be included in the sidebar in the default template.

How do I generate non-English dates?

Chronicle uses the Date::Language module for generating localized dates. For each of the variables "date", "time" and "date_short" there exists a corresponding variable with the suffix "_loc" ("date_loc" etc.) that contains the localized version.

For historical reasons, the language is configured via the environment variable $MONTHS. For example, to get Finnish dates, you could use:

    MONTHS=Finnish chronicle ...
How do I ignore draft-posts?

If you add the header draft: 1 to your pending post then it will be excluded from the blog, via the Chronicle::Plugin::SkipDrafts plugin.

How do I schedule future-posts?

If you add a publish: header, rather than a date: header, to your posts it will allow you to schedule the release of future posts via the Chronicle::Plugin::PostSpooler plugin.


This module is free software; you can redistribute it and/or modify it under the terms of either:

a) the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version, or

b) the Perl "Artistic License".


Steve Kemp <>