Watch
Postcraft, my massively overengineered static site builder just got a bit more complicated (but a lot more efficient). It's actually a series of apps ("transmissions") using Transmissions, my pipeliney thing. This is what they used to do :
- md-to-sparqlstore - walked a given dir on my local fs, reading all the markdown files, posting these off to a SPARQL store
- sparqlstore-to-html - queries the SPARQL store and renders the individual results as HTML pages
- sparqlstore-to-site-indexes - ditto, to make an
index.html
of recent posts
For every new blog post I made, every single one of the hundreds of existing posts also got re-processed. Not very efficient.
So I've added a filesystem Watch service. When a file changes, then it goes through the processing.
When I say I, Claude Code did most of the work. I have looked at node's watch
before and it is relatively straightforward to use. But there was a fair bit of textbook-like code that needed implementing. Now I have a watch-config.json
that looks like this:
[
{
"name": "postcraft-render",
"dirs": [
"~/sites/danny.ayers.name/postcraft/content/raw"
],
"apps": [
"md-to-store ~/sites/danny.ayers.name/postcraft",
"store-to-html ~/sites/danny.ayers.name/postcraft",
"sparqlstore-to-site-indexes ~/sites/danny.ayers.name/postcraft"
],
"watchEvents": [
"change"
]
}
]
It watches dirs
and on changed files triggers a call to the apps
in sequence. The path given with each app is the location of a tt.ttl
file which contains the settings for the app. Here's the core of the transmissions.ttl
for md-to-store
:
:md-to-store a :Transmission ;
:pipe (:p10 :p20 :p30 :p40 :p50) .
:p10 a :Restructure ;
:settings :prepFilename .
:p20 a :FileReader ;
:settings :readerSet .
:p30 a :Escaper .
:p40 a :MakeEntry ;
:settings :entryExtras .
:p50 a :SPARQLUpdate ;
:settings :storeArticle .
Here are the statements for the settings for Restructure
process :
:prepFilename a :ConfigSet ;
:rename (:pf1) .
:pf1 :pre "sourcePath" ;
:post "sourceFile" .
Restructure
modifies the shape of the data, a message passed along the pipeline transmission in the form of a JSON object. It's needed here because the watch system does a call using sourcePath
as the name of the changed file, but the Filereader
process expects a sourceFile
.
Like I said, this is all seriously over-engineered for a static site builder. But the component processors like Restructure
and Filereader
have no direct coupling and are totally reusable. A major reason for applying this to the static site builder is that the posts going into the SPARQL store are now part of my Personal Knowledgebase. Using that is over in the realm of Semem.
Having said all that, what I don't have yet is an easy way of tidying up. I created lots of blog entries in setting this up, the only reliable way I have for cleaning now is to empty the graph in the SPARQL store and run the process-everything transmissions. Hey ho.