Quick bits:
-
New ink for my fountain pen: oxblood. Delightful.
-
Happy winter solstice!
-
Tarmak-2 is going strong. I think I might be ready to switch to Tarmak-3 soon. But I’m taking my time; there is no rush.
Now I’m thinking about how to swap the keys on my MacBook Air’s built-in keyboard. Is that doable, safely?
Aggravatingly, my MacBook Air has started, once again, reverting to QWERTY every time it wakes up and every time I log in. There is neither rhyme nor reason to this madness.
-
A random bad memory from a previous job: I once used subtasks in Jira, which made my coworkers genuinely angry. This is not how we work here, they said. Taking down production would’ve gotten me less flak.
-
GitHub’s UI has gotten phenomenally bad. My work MacBook Pro has 12 cores and 24 GB of RAM, yet there are pull requests for which it is difficult to write a description because the input lag in the description field is multiple seconds.
-
I started drafting my year-in-review note for 2025.
Shower thoughts:
-
A quick German lesson for y’all: bedroom = Schlafzimmer; dining room = Esszimmer; music room = Hanszimmer.
-
Perhaps not strictly a “shower thought,” but when speaking with my acting classmates, I discovered that I am not the only one practicing their monologues in the shower. Perhaps this is just a very natural place for it.
My first1 theatre performance was a success!
We were close to a full house: 45–50 people showed up, which is considerably more than I anticipated.2
Things came together only last minute. Not everyone could be present at the last two rehearsals, and we never managed to get a full run-through of the show. Things kept changing even on the day of the performance. But you know what? It all worked out. It all came together beautifully, and I’m proud of myself and of the entire ensemble.
I’ve come to realize that I do my best work when there is an audience — when there are stakes.
So what is next for me? There is a similar course starting in January, also finishing with a public performance. The timing isn’t great, however: it’s unlikely that I’ll able to participate in that public performance. This would limit me to doing monologues; it’s unlikely that I’ll find a scene partner willing to put in effort into a scene that wouldn’t be performed. I’m not sure how I feel about just doing monologues (again). I’ll have to think about it.
This week, I once again had the urge to pick up photography. I’ve got a good eye3 and I remember having a good amount of fun with it in the past. It was challenging yet rewarding, and that is the reason why I am drawn to it once again.
Here are some old photos4 that I’m happy with, from an embarrassingly long time ago — well over a decade:



The only camera I have is my iPhone 14 Pro. It should be decent for photography, but I really miss having manual controls. I have Halide but never really used it; it’s a decent app, but I crave a dedicated camera. I’d love to have a zoom lens, or at least a couple of swappable prime lenses. Having had a decent camera in the past,5 I find the iPhone so limiting as a camera.
It’s nice to have a dedicated camera; it encourages taking photos in a way that a phone camera does not. It’s a good way of creating memories. I’ve gone on trips that resulted in a good series of photos that aren’t just holiday snaps, but tell a story — my story, my interpretation, my experience. I also think it’s great to bring a camera on trips with friends; people tend to quite appreciate good photos of themselves.
Still, I am dreading how much time and effort it will take to pick it up again and become reasonably good at it. Do I have the time? Not sure. Is it worth investing in a good camera? No idea. Where do I want to go with this hobby? Also no idea. Perhaps at some point in the future, I’ll simply stop asking myself that question, buy a good-enough camera and just start using it instead of thinking about it.
Notifications continue to be the bane of my existence. My work laptop has a bit of an issue:
-
I get a macOS calendar notification that I have an upcoming meeting.
-
I get a Slack message notifying me of my upcoming meeting.
-
I get a macOS notification that I have a Slack message notifying me of my upcoming meeting.
-
I get an email notifying me of that Slack message notifying me of my upcoming meeting.
-
I get macOS notification about this email notifying me of that Slack message notifying me of my upcoming meeting.
Ahh yes — notifications about notifications. Meta-notifications. Wonderful. Slowly but surely, I’m fixing it; I can feel that 2026 will be the year of proper notifications.
In the context of building a next-generation static-site generator, I’ve been thinking about better abstractions for incremental computation. By having a more formally defined model of incremental compilation/computation, it will be easier to reason about the model, and I believe it could lead to significant performance gains.
I found Rado Kirov’s introduction to incremental computation quite useful as a baseline.
The writing on incremental computation is sparse, and it makes me think that there hasn’t been all that much research and exploration into this domain.6 This is a little unfortunate for me, but also rather exciting. More stuff for me to discover and research!
For this next-generation static-site generator, incremental computation is challenging for a few reasons:
-
Inputs from the filesystem: Changes on the file system are surprisingly tricky to track properly. Moves/renames, for example, typically appear as if an old file is deleted and a new file is created with the same content but a different name.
-
Outputs to the filesystem: The end result of a site compilation is a bunch of files in the output
/ directory. But how would you detect output files which are stale, i.e. for which no computation exists anymore? Nanoc already handles all of this, to be clear. But it also has an entirely separate process (the pruner) that runs after compilation is complete. It works, but there’s no neat formal model behind it.
-
Collections: A computation that depends on a list will typically have to be re-run when that list changes. But is there a way to be more fine-grained? What are the ways in which not the entire computation has to be re-run? Storing items/files in prefix trees (tries) rather than lists could be helpful.
-
Unused arguments: If a computation has a parameter that isn’t used in that computation, then the computation shouldn’t be triggered if the value of that parameter changes.
-
Persistent incrementality: I want incremental computation not just while the process is running, but also between runs. This will require incremental computation state to be persisted, and be able to be loaded and stored quickly — perhaps even queryable on disk.
-
Pull-based: When live recompilation and live reloading is active, I’d like to prioritize compilation of items that are being used in the browser. This is an optimization that spreadsheets already have: computed fields on invisible worksheets are ignored until the worksheet is tabbed to.
-
Chiastic inclusion:7 It needs to be possible for two pages to include each others’ content from an earlier stage in the compilation process. This requires compilation/computation to be non-atomic and interruptible or suspendable.
-
Dynamic computation graph: The computation/compilation rules are not static, and can change between runs. An incremental change to the computation rules should also yield an incremental change to the computations themselves. There’d need to be a way to diff not just inputs, but also computation rules.8
I know all of this is very abstract still, and I’m mostly just thinking out loud — or writing out loud, perhaps — while I am figuring this out. Perhaps some of this will stop making sense even to me a few days from now.
Imagine having a scripting language with incremental computation built in, allowing you to write a script rather than having to limit yourself to the strictness required by a Rules
It’d be great if the execution time could be linear in the size of the changes, rather than linear in the size of the site. Wouldn’t it be great if it didn’t matter if a site had ten pages, or ten million?
For the time being, I am putting the work on my Zig-based static-site generator on hold. I want to figure out this incremental computation first, as I think there’s a ton of potential there. As for the implementation language for this incremental prototype, maybe Ruby isn’t the worst — it still is, in fact, my favorite language, and great for prototyping.
Building a good static-site generator is surprisingly hard.
I have, at long last, brought order to the chaos that was the import of all my notes from Bear into my web site.
Up until recently, all my notes (including weeknotes) ended up in the content
Not that it was too much of an issue for me: I almost exclusively use Bear to write, edit and otherwise manage my notes (and weeknotes), so having a giant content
-
Weeknotes (e.g. content
/notes /F66AD4A3 ‑68DF ‑4A2B ‑80BB ‑D495CFC99123 .md ) now reside under content /weeknotes /, organized by year (e.g. content /weeknotes /2025 /w50 .md ). -
Notes with slugs (e.g. content
/notes /7B2E0457 ‑325F ‑4564 ‑BEDF ‑D3338AAE4410 .md ) now use that slug, as opposed to the note ID, in their filename (e.g. content /notes /zig .md ).
The best part about this rather intrusive change is that… well, nothing changes for visitors. The compiled site is the same. The URLs and IDs — such as the oh-so-important Atom ids — have not changed.9 There is no disruption. Smooth as butter.
I’ve made full use of Nanoc’s ability to decouple input from output. What a great piece of software.
Entertainment:
- I went in to Get Out10 thinking of it as a horror movie — which it certain is, too — but I did not expect to get satire. Thoroughly enjoyable and I’m surprised it took me this long to get to it.
Links:
-
How I Copyedited Shirley Jackson (Benjamin Dreyer): What an honor it must be to copyedit Shirley Jackson!
-
Berlin: Police can secretly enter homes for state trojan installation: This is dystopian.
-
Why Does Monopoly Start Arguments?: The London History Show: This is why it’s consistently ranked near the bottom on Board Game Geek.
-
It's All Henry VIII!: A Beginner's Guide To The Dissolution of the Monasteries (J. Draper)
-
Your 2025 Train Delay Wrapped (chuuchuu): I am surprised by how badly Germany is doing. Belgium, in my mind, consistently was far worse. But apparently not?
-
The Berkshire Mystery: Where Exactly Is “Berk”? (The Tim Traveller and Paul Whitewick)
Tech links:
-
Ruby Programming Language: New Ruby site dropped and it looks neat! Definitely an improvement. Except for the DHH jumpscare.
-
Typeframe PX-88: Ooh, I love this. It’d be so neat to have a low-power distraction-free computer that I can carry with me.
-
Non-Violent Comments: Calling out or Calling in? (Richard Schneeman)
-
It is not strictly the first — not even the second. But I think this is the first public performance that counts: the first one that I genuinely trained for, where I used actual technique, and where my efforts noticeably paid off. ↩︎
-
When F—— asked me whether it was worth reserving tickets, I said “probably not” which very nearly was a mistake. I didn’t anticipate us — a bunch of acting students — to attract such an audience. That’s nice, but also: oops! ↩︎
-
Some of my photos (from many, many years ago) have ended up in a couple of well-known places, in both online and offline media. ↩︎
-
Recropped to 2:1 because that is what I fancy now. ↩︎
-
I had a Nikon D40, which by no means was a great camera (low resolution and very grainy), but it taught me a lot about photography and it got me hooked. ↩︎
-
It’s also quite likely that I am not good at doing research. ↩︎
-
Am I giving this concept a fancy name because I can? Because I am sophisticated? Yes — yes indeed. ↩︎
-
I might have to create my own programming language for this specific purpose. How exciting! ↩︎
-
The URLs of some images have changed. This is intentional. There is no redirect, which I think is reasonable. ↩︎
-
Get Out, directed by Jordan Peele (Universal Pictures, Blumhouse Productions, QC Entertainment, 2017). ↩︎