tilstream is the small static-site generator I wrote for my Today-I-Learned feed, and this cast is the complete flow from empty directory to post published on S3.

tilstream init lays down four files: tilstream.yaml for config, a .gitkeep in posts, a template for post rendering, and a default theme. Then tilstream new '...' creates a dated markdown file for a new post. I pretend to edit it (in reality the file has a sensible front-matter skeleton and a blank body, ready to write into).

tilstream build renders everything into public/. Notice that the output is three files per post: an HTML page, a slug directory, and a feed entry. The index and the feed XML are regenerated on each build from the union of all posts.

tilstream serve --port 4000 spins up a local preview server. The GET lines in the cast are me clicking around in a browser you can’t see. When I’m satisfied I Ctrl-C and run tilstream publish, which diffs public/ against the configured remote (here, an S3 bucket) and uploads only the changed files.

Callouts:

  • tilstream is opinionated about the post format. If you want full Hugo flexibility, use Hugo. tilstream gives up configurability in exchange for a tiny surface area.
  • publish is a content-addressed diff, so re-uploads are almost always only the one file you actually changed, plus the index.
  • The whole build is 38ms for one post. A thousand posts still builds under a second on my laptop.

It is very much overkill to write a static-site generator for a TIL feed. I know. I wrote it anyway because the existing ones had shapes that didn’t fit.