The devlog

Stories from actually building these apps, written from the build records. Real bugs, real numbers, honest dead ends. No tutorials, no filler.

Telemetry

Deriving racing truth from a free, undocumented Formula 1 data feed.

Matchday Data

Building a live World Cup match centre on a public feed full of quirks.

Engine Room

Desktop infrastructure: Electron, process supervision, and the Windows wallpaper layer.

Postmortems

Bugs that earned a full write-up, and what they taught.

Engine Room11 July 2026 · 3 min

Never hash JSON.stringify for identity

My process launcher decided whether a running app was the one it knew by hashing its config. Reordering two keys in that config, with no change in meaning, made it kill a perfectly healthy process on the next boot.

Postmortems11 July 2026 · 3 min

The overlaps a screenshot hides

A layout can look fine in a screenshot while one element sits 121 pixels on top of another. The fix was to stop looking at pictures and start measuring bounding boxes, and to always test the widest and shortest screens where the bugs actually live.

Postmortems11 July 2026 · 3 min

The panel that was empty for all 48 teams

Every team page in my World Cup tracker had a record panel that showed nothing, and nothing complained. The bug was a contract mismatch: the frontend read a field the backend never populated, and a missing field is invisible to almost every guard you have.

Engine Room10 July 2026 · 4 min

The backend a free trial took offline

A free trial ended and took my World Cup tracker's backend down for days during the knockouts. The fix was to stop having a separate backend at all, and fold the data layer into the Next app so there is one host and nothing left to lapse.

Engine Room5 July 2026 · 6 min

Building a Steam client for my own software

Three overlapping desktop apps became one small kernel with a single manifest schema. Why no runnable type gets special treatment, and the deletion test that decided when the kernel was real.

Telemetry3 July 2026 · 5 min

A centreline the cars drew, and lap times within a second of the feed

F1's free feed gives car positions as noisy XY samples and lap times from hardware in the tarmac. I projected every sample onto a derived centreline as arc length plus lateral offset, computed lap times from geometry alone, and checked them against the feed's own clocks.

Postmortems3 July 2026 · 4 min

A hydration mismatch hiding in the 14th decimal place

React said my server HTML didn't match the client. The diff was two numbers that agreed to thirteen significant digits. The story of why Math.sqrt is allowed to do that.

Matchday Data3 July 2026 · 6 min

A radial knockout bracket, and the draw that refused to pair neighbours

I rebuilt the WC26 knockout bracket as a radial fan chart. The curves were the easy part. The real draw pairs non-adjacent matches, losers deserve a visible line too, and one wrong ARIA role quietly flattened 62 interactive nodes into a single image.

Telemetry3 July 2026 · 5 min

Deriving lateral G from a feed that doesn't have it

F1's free timing feed carries five telemetry channels and none of them is cornering force. I derived lateral G from speed and line curvature, added throttle and braking stats, and checked the whole pipeline against the one number the feed also publishes.

Telemetry3 July 2026 · 6 min

Drawing an F1 circuit from nothing but where the cars drove

F1Peak ships no hand-drawn track maps. Every circuit outline is computed from the cars' own position data, as a median over many resampled laps, with dirty laps rejected and the start/finish seam parked next to the pit lane.

Telemetry3 July 2026 · 5 min

No curvature threshold can number Monaco

F1Peak derived corner numbers from track curvature, and Monaco broke it in both directions at once - a 25% dead zone or 39 phantom corners, depending on the threshold. The fix was to admit that official turn numbers are a human list, and to snap that list to the real apexes.

Matchday Data3 July 2026 · 5 min

Quirks are law: building a World Cup tracker on a free ESPN feed

The free ESPN feed behind WC26 pre-rounds its percentages, counts its clock in seconds, and silently caps a ranged schedule request at 100 events. Every quirk I found became a hard rule in the code, because the feed was never going to change.

Telemetry3 July 2026 · 5 min

Smoothing 3.7 Hz GPS into 60 fps car motion

F1's position feed reports each car under four times a second, with up to two metres of noise. How F1Peak turns that into fluid on-track motion with centripetal Catmull-Rom splines and dead reckoning, and how I proved the result with heading statistics instead of a feeling.

Engine Room3 July 2026 · 6 min

Stop polling. The app already knows it's ready

My desktop engine's HTTP ready probe was killing a healthy server for answering slowly. I replaced pull-based health checks with a push rail - a loopback-only listener, a per-launch token, and a client library that silently no-ops when the engine didn't launch the app.

Telemetry3 July 2026 · 6 min

The free data path behind Formula 1's live timing

F1's official live-timing player is fed by a public static file tree plus a SignalR socket, most of it reachable without a key. The recipe from building F1Peak, including the BOMs, the raw-deflate payloads, the per-topic auth, and the 30-minute publication delay.

Postmortems3 July 2026 · 6 min

The junction that broke every launch, twice

I moved one project to an SSD and left a directory junction behind. Node canonicalised paths through it, every sibling launch in my desktop engine died with ENOENT, and my first fix quietly failed in the packaged exe depending on how you double-clicked it.

Postmortems3 July 2026 · 5 min

The readiness probe that kept killing a healthy app

My desktop engine kept declaring a healthy Next.js app dead and killing it. The probe's hardcoded 1.5 second per-attempt cap sat below the app's real render time, so every attempt failed against a server that was answering 200s.

Matchday Data3 July 2026 · 6 min

The shot map ESPN was handing us for free

My World Cup tracker's plan said shot coordinates were impossible without faking data. Then I read the raw feed and found real pitch coordinates and kick-by-kick shootout data, fetched on every request and thrown away by my own normalizer.

Engine Room3 July 2026 · 5 min

The wallpaper is just another window

The recipe for rendering an Electron app as the live Windows 11 wallpaper, from the WorkerW window layer and click-through widgets to the day the ZQ Engine absorbed the whole trick as a tenant.