SEOBuild Log
#211
2026-06-195 min read

Google ranks URLs, not intentions: the NN- prefix strip that resolved eight cannibalisation pairs on ukcalculator.uk

A site-wide SEO audit of ukcalculator.uk surfaced eight cannibalisation pairs before a single meta-tag was touched. The common thread: a numeric sort prefix on every affected slug, one that had never been intended as a ranking signal. Fixing the URLs outweighed everything else in Phase 1.

Read post→
Build LogiOS
#212
2026-06-185 min read

Five features, one PR: how an iOS budget app ships concurrent phase work without a merge queue

On 2026-06-14, five feat entries landed in an iOS budget app across Phases C, D, and E — all tagged 'same PR #10.' Treating commits as the concurrency primitive instead of branches let three phases advance in parallel without a merge queue or conflict chain.

Read post→
iOSSwiftUI
#213
2026-06-186 min read

I could have built this twice. ModuleOrderStore is why I didn't.

Making Home and Accounts modules user-rearrangeable could have meant two separate order stores, one per screen. ModuleOrderStore — a @MainActor singleton mirroring an existing PaletteStore pattern — is the reason it's one. The device QA round on AnF confirmed the ordering engine held; six other issues confirmed the QA was necessary.

Read post→
Build LogiOS
#214
2026-06-186 min read

One parser for Monzo, Halifax, Revolut and HSBC: how heuristic matching beat four bespoke importers

The on-device LLM for PDF extraction hallucinated on a real Halifax statement. That failure produced a band-based parser that hits 54/54 transactions. The same heuristic approach on the CSV side means one importer, four banks, zero per-bank code paths.

Read post→
Build LogiOS
#215
2026-06-185 min read

SoundCloud showed up under my Google Cloud rule on device. That's when part-based matching replaced the algorithm.

Phase Q shipped smart category propagation powered by a fuzzy matcher. Device QA of the Phase R match builder found the structural over-reach immediately: ANY-match on GOOGLE and CLOUD pulled SoundCloud in via 'cloud' and two Google One rows in via 'google'. Phase R v2 added exclude words and per-row select-all to close the gap — because a rule you can read is a rule you can fix.

Read post→