From The Architect

Notes on architecture, platforms, and data — plus the GNOME apps, home automation tinkering, and open source projects I’m building along the way.
Moments: The Photo App I Built to Win an Argument

Moments: The Photo App I Built to Win an Argument

A phone call with a mate turned into a wager: could AI actually build a real application from scratch? Five months, 898 commits and 40,000 lines of Rust later, here’s the verdict — and the app. It started with a phone call Like most of my questionable decisions, this one started on the phone with a mate, talking about technology the way we always do. The conversation drifted, as every technical conversation eventually does now, into AI. And we ended up circling the same question everyone circles: is this stuff actually capable of building real software, or is it just very confident autocomplete? ...

August 13, 2026 · 11 min · Justin
Building GNOME Apps with Rust, Part 6: Fetching Feeds

Building GNOME Apps with Rust, Part 6: Fetching Feeds

This is Part 6 of a series taking a GNOME app from an empty directory to GNOME Circle. Part 5 wired the sidebar to a real Feed GObject and a feed-selected signal — selecting a row updates the content pane and prints a line to the terminal. This is the post where that line stops being a placeholder and becomes a real network fetch. The click that still does nothing real Select This Week in GNOME, then select Hacker News. The placeholder swaps in the new name and URL — everything the app knows about that feed, and none of what’s actually in it. Every Feed in the sidebar has a uri pointing at a real RSS or Atom document on the actual internet, and nothing in the codebase has ever asked one of them what’s there. ...

August 11, 2026 · 19 min · Justin
Stop Thinking in Rows: GListModel and the Modern List Mindset

Stop Thinking in Rows: GListModel and the Modern List Mindset

This is the third entry in A Field Guide to GTK Widgets — a series about which widget to reach for, when, and what bites you when you do. We’re jumping straight to lists, ahead of layout and navigation, because it’s the material the reference documents worst. Each post stands on its own, and the complete, runnable code for this one lives in the companion repo. The list you’d build without thinking Say you’re showing a handful of tasks. The obvious way to do it doesn’t require reading any documentation at all: ...

August 11, 2026 · 10 min · Justin
Two YubiKeys, One Prompt Too Many

Two YubiKeys, One Prompt Too Many

I carry two YubiKeys. One lives on my keyring, one lives in a drawer, and both are enrolled everywhere that matters. A hardware token with no backup is a single point of failure you have chosen on purpose. For months I had a small irritation I never bothered to chase. Some days git push asked for my PIN, I typed it, and it worked. Other days it asked for my PIN, failed, and then asked again, and the second one worked. Same command, same repo, same laptop. The variable turned out to be which of the two keys happened to be in the USB port. ...

August 7, 2026 · 10 min · Justin
Excavating Legacy ETL

Excavating Legacy ETL: The AI Never Asserts a Fact It Could Look Up

Every platform modernisation programme has the same first act, and it is never the interesting one. Before anyone gets to write a line of dbt, somebody has to work out what the current thing actually does. In the SAP BusinessObjects Data Services case — BODS, if you’ve had the pleasure — that means inheriting a few hundred dataflows whose authors left the organisation years ago. The logic lives in exported XML. The business rationale lived in the heads of people who are now at other companies. Nobody can tell you which flows are duplicates, which ones nothing reads any more, or what any given one is for. There is a spreadsheet somewhere claiming to be an inventory. It is wrong in ways nobody can enumerate. ...

July 21, 2026 · 16 min · Justin
The Application Shell: GtkApplicationWindow vs AdwApplicationWindow

The Application Shell: GtkApplicationWindow vs AdwApplicationWindow

This is the first proper entry in A Field Guide to GTK Widgets — a series about which widget to reach for, when, and what bites you when you do. We start where every app starts: the window. Each post stands on its own, and the complete, runnable code for this one lives in the companion repo. Two windows, and the one you should reach for You sit down to write a GNOME app. The very first widget you need is the window, and the toolkit immediately hands you a choice it doesn’t explain: GtkApplicationWindow, from GTK itself, or AdwApplicationWindow, from Libadwaita. The reference describes both accurately and tells you nothing about which one you want. ...

June 12, 2026 · 9 min · Justin
A Field Guide to GTK Widgets

A Field Guide to GTK Widgets

This is the opening post of a series that works through GTK4 and Libadwaita together, one practical interface decision at a time. The posts are grouped around the things you actually build — a window, a list, a settings page — rather than the library a widget happens to ship in. Each post stands alone; together they’re meant to be the field guide the reference documentation isn’t. The problem with the reference The GTK4 documentation is genuinely good. Every widget has a page. Every property, signal, and method is listed. The class hierarchies are accurate and the prose is precise. If you already know which widget you need, the reference will tell you everything about it. ...

June 5, 2026 · 9 min · Justin
Building GNOME Apps with Rust, Part 5: State and Signals

Building GNOME Apps with Rust, Part 5: State and Signals

This is Part 5 of a series taking a GNOME app from an empty directory to GNOME Circle. Part 4 replaced our XML templates with Blueprint and grew the window into the real Gazette layout — a sidebar, a content pane, and three typed widget handles waiting for behaviour. This is the post where they get some. If the GObject machinery in here feels unfamiliar — mod imp, properties, signals — Part 2 is the reference. This is where those patterns stop being theoretical. ...

June 2, 2026 · 20 min · Justin
Four Ways the Outbox Bit Me

Four Ways the Outbox Bit Me

In the previous post I described an architecture where the Moments library doesn’t know that sync exists. Services record Mutation values into a one-method trait; one implementation writes to an outbox table, another does nothing. The library code is identical regardless of which backend it’s running under, and a third backend could be added without touching the library at all. The architecture is sound. I still believe in it. The first six weeks of running it were a different story. Four bugs in particular are worth describing, because each one tells you something the diagrams don’t. Two are about the abstraction — assumptions the trait quietly makes about how the world works, and what breaks when the world doesn’t cooperate. Two are about the substrate — the boring queue-and-retry machinery underneath the trait, which has its own opinions about how things should be done. Clean architecture doesn’t relieve you of the substrate’s problems. It just gives you one place to deal with them. ...

May 31, 2026 · 12 min · Justin
Why Open Source Doesn't Embrace AI

Why Open Source Doesn't Embrace AI

A week ago I would have told you the open source community rejected AI for four obvious reasons. Then I tried defending each one properly. Most of them collapse under scrutiny — and what’s left is a much more tractable conversation. The conventional answer Every maintainer I know has roughly the same three or four complaints about AI tooling. First, nobody can tell where the training data came from, which sits badly with a culture obsessed with provenance. Second, maintainers are drowning in AI-generated PRs and CVE reports — Daniel Stenberg’s posts on the curl side of this are now the canonical example. Third, AI shortcuts the old apprenticeship loop where contributors learned a codebase by earning review trust over months. And fourth, the power asymmetry: frontier models need hyperscaler capital, which sits uneasily inside a movement built on “you can read, modify, and redistribute the thing.” ...

May 27, 2026 · 10 min · Justin