The Shape of Decoupling

The Shape of Decoupling

There is a moment in every codebase where someone draws a box on a whiteboard, labels it EventBus, and draws arrows fanning out to every other box. The room nods. It looks like architecture. It looks like the right architecture — loosely coupled, extensible, the textbook answer to “how do we let many components react to one thing happening?” That diagram is a trap. I drew it for Moments, my photo manager, in late March 2026. I had the design reviewed by an external UI architect. I shipped it in April across six phased PRs. And on the third of May I deleted the whole thing in a single commit titled, with some satisfaction: ...

May 10, 2026 · 8 min · Justin
Building GNOME Apps with Rust, Part 4: Blueprint

Building GNOME Apps with Rust, Part 4: Blueprint

This is Part 4 of a series taking a GNOME app from an empty directory to GNOME Circle. Part 3 walked through every file Builder generated for our gazette project. Now we’re going to start changing things. If you’re new to this stack and wondering why GTK and libadwaita are separate libraries, why GObject’s type system feels like 1990s C, or why Flatpak ships its own runtime alongside your app, there’s a short companion piece on the history of the stack. Skim it for context or skip it for code. ...

May 6, 2026 · 14 min · Justin
Building GNOME Apps with Rust, Bonus: The Stack Underneath

Building GNOME Apps with Rust, Bonus: The Stack Underneath

This is a bonus post in the series taking a GNOME app from an empty directory to GNOME Circle. It sits between Part 3 and Part 4 — read it if you want context, skip it if you want code. By the end of Part 3 you had a running GTK 4 + libadwaita app with five trait implementations, a mod imp block, an adw::Application parent class, a meson.build next to your Cargo.toml, and a Flatpak manifest pinning a runtime version. None of those decisions arrived in 2026 fully formed. Each is a fossil of a specific argument that took years to settle. ...

May 5, 2026 · 8 min · Justin
Building GNOME Apps with Rust, Part 3: Your First App

Building GNOME Apps with Rust, Part 3: Your First App

This is Part 3 of a series that takes a GNOME application from an empty directory to acceptance into GNOME Circle. Part 2 covered GObject’s type system — properties, signals, and the inner/outer type pattern. Now we’ll use everything we learned to build a real application. From theory to a running window In Part 2 we built a GObject subclass by hand — a Feed model with properties and signals, no GTK in sight. That was deliberate. Understanding GObject’s inner/outer type split, the ObjectSubclass trait, and the mod imp pattern is the foundation that everything else rests on. ...

May 3, 2026 · 16 min · Justin
Making a Dumb Fridge Smart

Making a Dumb Fridge Smart

There’s about $400 of meat, milk, and miscellaneous condiments in my kitchen fridge at any given time. It runs 24/7, makes a quiet humming noise, and gives no indication when something’s wrong until you open the door three days later and recoil. The freezer compartment is worse: a slow failure can defrost everything before you notice the puddle. I already had a TP-Link P110 smart plug on the fridge — originally for energy monitoring, because I’m on a spot-priced electricity tariff and I like knowing what each appliance costs me. But the same wattage stream that tells you “the fridge used 1.4 kWh today” tells you almost everything you need to know about whether the fridge is healthy. ...

May 3, 2026 · 9 min · Justin
Building GNOME Apps with Rust, Part 2: GObject in Rust

Building GNOME Apps with Rust, Part 2: GObject in Rust — The Type System Explained

This is Part 2 of a series taking a GNOME app from an empty directory to GNOME Circle. Part 1 covered the why and the dev environment. The app we’re building Throughout this series, we’ll be building Gazette — an RSS reader. I picked it because it naturally exercises every pattern a non-trivial GNOME app needs: networking, data persistence, list/detail UI, adaptive layouts, settings, and state management. You don’t need to build an RSS reader to follow along — the patterns are universal. ...

April 12, 2026 · 7 min · Justin
Building GNOME Apps with Rust, Part 1: Getting Started

Building GNOME Apps with Rust, Part 1: Getting Started

This is Part 1 of a series that takes a GNOME application from an empty directory to acceptance into GNOME Circle. Each post is self-contained, but the series follows a single arc — and a real app — through every stage of the journey. Why GNOME If you’re building a desktop Linux application in 2026, you’ve got choices. KDE Plasma has Kirigami. Elementary has Granite. You can reach for Electron, Tauri, or a dozen other cross-platform toolkits and call it a day. ...

April 6, 2026 · 9 min · Justin
The AI Pair Programmer

The AI Pair Programmer: Why the Human Loop Is About Partnership, Not Review

What Extreme Programming taught us about collaboration — and why it maps perfectly onto working with LLMs The current conversation is missing something If you spend any time in developer circles right now, the conversation about AI coding tools tends to collapse into one of two camps. The first camp believes we are months away from AI replacing software developers entirely — that the role of the human is already vestigial, a temporary inconvenience on the road to full automation. The second camp pushes back hard, arguing that AI is little more than a sophisticated autocomplete — useful for boilerplate, dangerous if trusted, and nowhere near capable of producing anything a senior engineer couldn’t do faster with a clear head and a good keyboard shortcut. ...

March 25, 2025 · 17 min · Justin