simple site generator
add link to rbn.im repo
add documentation
add main script detection, wrap procs in namespace


browse  log 



You can also use your local clone with git send-email.


builds.sr.ht status

simple & flexible templating.


i've gotten annoyed by other static site generators doing a million things. i just want to generate some html pages. so this.


NB: a more complete example is my personal page

create a hierarchy like the following:

  • content

    • page
      • content.md
      • data.tcl
  • global

    • date.tcl
  • template

    • template.html

then run tlog:

tlog.tcl -t template/template.html global page

this uses template.html as template, reading contents to be inserted from global and page.


a template can be anything plaintext. as subst is the mechanism used, it's rules apply.

a template thus looks kind of like this:


[ insert title ]

[ insert date ]

[ insert content ]

the insert command is another way to insert variables, as a way to have a fixed way to insert stuff in case the internal data representation changes (which it has done multiple times already :P) without requiring touching contents.


content is always consumed as whole directory, the names of the files without extension are being used to reference the contents from a template.

a tradeof which is being made is that contents can be preprocessed. while this could be done in an additional external step, it's common enough to be included. currently there are three types of content:

  • markdown (extension .md) parsed & formatted as html with tcllib "Markdown"
  • tcl (extension .tcl) is evaluated and can reign freely. the output is also stored.
  • html (extension .html) is just copied.

as contents are a whole directory, we can do without the thing other systems call "frontmatter" by evaluating tcl scripts in the content directory.

there can't be contents of the same name, so data.md and data.tcl aren't permitted, not even when in two different directories (as we can load multiple ones). reading the contents of the same name will error out to avoid confusion.

examples for contents:

$ cat content/page0/content.md
# foobar
it's markdown!

$ cat content/page0/data.tcl
dict set context title "the title"

$ cat global/date.tcl
proc date {} {
	set date 0
	foreach { path } [ glob -type f * ] {
		set ndate [ file mtime $path ]
		if [ expr $ndate > $date ] {
			set date $ndate
	return [ clock format $date -format %Y-%m-%d ]

dict set context date [ date ]


contents are read into the context dictionary, with their filenames without extension used as keys. tcl script contents can modify the context dictionary as in the example above.

this context dictionary gets unpacked using dict with before running subst with the template as argument.


to tie everything together, you can use make:

output/%.html: template/template.html global/date.tcl content/%/content.md content/%/data.tcl
	tlog.tcl -t template/template.html global content/$* > $@


in the example directory is a somewhat complete way to build a simple blog.