[Software] · Aug 19, 2026 · 7 min read
Reviving Word Tracker: What a Three-Year-Old Codebase Taught Me About Structured AI Development

I’m happy to announce that I’ve released a new version of Word Tracker, my app that helps writers track their project progress. Getting here was a long journey — one abandoned migration, two very different attempts at using AI, and a lesson that ended up reshaping how I build with AI agents altogether.
Where It All Started
Word Tracker was first built and actively maintained between 2020 and 2022. The tech stack I chose back then — based on what I knew and used most at the time — was UIKit for the presentation layer, Realm for local data persistence, and a fairly full Firebase suite: Analytics, Crashlytics, Remote Config, Auth, and — most importantly — Firestore for cloud storage. On top of that sat a handful of my own Swift Packages, handling Realm model management, custom surveys (Survey), and reusable views and view factories (ViewFactory) — pulled in through both Swift Package Manager and CocoaPods.
At the time, I didn’t fully register how long that dependency list had become for such a small app. But it all made sense in isolation. I wanted users to move between devices, which meant Firestore, which meant a full authentication flow, which meant a sync manager to keep Realm and Firestore in step. Since I’ve never been a fan of paywalls or ads, I monetised the “cloud sync” feature as a one-off in-app purchase instead — not critical to the app’s core functionality, but a way to earn a little from the work. Some users bought it without needing it at all, purely to support the app. That kind of quiet appreciation stays with you.
Three Years of Silence, and a Codebase Gone Stale
Between 2022 and 2025, I moved on to other projects, and Word Tracker sat untouched. For non-technical readers: three years without code maintenance is a long time in software. Most of my dependencies had gone through major version bumps in that window, and major bumps almost always mean breaking changes.
I started by trying to update everything manually. It didn’t take long to realise the old architecture no longer made sense — patching version bumps on top of a stack I’d design very differently today would only add complexity. So I decided to go further and migrate the presentation layer from UIKit to SwiftUI as part of the same effort.
First Attempt: The One-Shot Trap
This was 2025, and I’d just come across Cursor. I figured I’d use the free tier to attempt a “one-shot” migration from UIKit to SwiftUI. That was the wrong call. AI tooling in 2025 promised a lot, but under the hood it made plenty of mistakes and introduced unrelated changes I hadn’t asked for. I ended up throwing the whole attempt away and put Word Tracker on the shelf again.
Second Attempt: Better Tools, Still No Structure
A year later, with AI no longer a novelty but something I use daily, I gave it another go — this time with Claude Code. At the start of this year I was still using it without much structure, still hoping a well-worded prompt could one-shot the hard parts.
This time, the UIKit-to-SwiftUI migration actually worked well and gave me a solid baseline. The legacy codebase helped here too — it had a good amount of Unit and, especially, Snapshot tests already in place, which made it much easier to review the AI’s changes, since I could see the exact UI differences directly in the test snapshots. But once the UI was no longer the blocker, I hit the part of the app that mattered most: the sync manager. It was the most complex piece of logic in the whole codebase, and getting it wrong risked something far worse than a UI bug — users losing their project data entirely. With every prompt, the AI kept adding more complexity to that sync manager rather than less, and no amount of rewriting my prompts or retrying different solutions got me past that. The closer I got to aligning it with the new SwiftUI views, the less confident I felt that the worst case wouldn’t happen. So I paused again.
The Idea That Actually Unblocked Me
A few more months of using Claude Code later, I’d developed a much more structured way of working — my own plugins with defined agents and precise, scoped skills. I migrated Word Tracker’s development to this new workflow, and partway through, something clicked: I no longer needed Firestore or Realm at all. Apple’s own CloudKit combined with SwiftData could replace both.
That single change removed the need for a custom authentication flow and, more importantly, the entire hand-written sync manager — SwiftData and CloudKit handle storage and cross-device syncing natively. Of everything in this migration, that was the idea that mattered most. It removed the exact risk that had made me pause twice before: the fear of silently losing someone’s writing progress during the transition.
What a Structured Agentic Workflow Actually Looks Like
With the riskiest part of the app now resting on Apple’s own frameworks instead of my own sync logic, I could finally work the way I’d wanted to from the start: breaking the migration into clear tasks for agents, running code reviews on their output, and testing with unit, UI, and snapshot tests executed on a separate machine, fully isolated from the agents doing the implementation. That let me focus my own attention on manual, high-level testing rather than checking every implementation detail by hand.
To be fully transparent, that didn’t mean I could skip code review entirely. Near the end, I still had to sit down and go through the code myself. Not a deep, line-by-line audit — but there were a handful of bugs the agents genuinely couldn’t fix, or where fixing one introduced another as a side effect. At that point, precision stopped being about high-level functionality and became about how something should actually be implemented. For Word Tracker, that was navigation: an unnecessary coordinator had crept in, and the main AppCoordinator kept growing more tangled with every AI edit. Only once I reviewed it myself, understood how it actually worked versus how it should have worked, and made the call to simplify it manually, could the agent take that clarity and simplify the rest for me.
The migration still took several attempts and more than one rethink of the approach. But a structured, repeatable workflow — rather than one big hopeful prompt — is what finally got it across the line.
The Real Lesson
I wrote in an earlier article about specs-driven development and why AI tends to struggle in codebases full of undocumented, implicit decisions. This migration was the practical proof of that idea. My first two attempts failed not because the AI wasn’t capable, but because I was dropping it into ambiguity and hoping for the best. What worked was giving the AI — and myself — clear architecture decisions, scoped tasks, and tests it couldn’t quietly break. If you’re bringing an old project back to life with AI, my honest recommendation is to resist the one-shot temptation: build up documentation, specs, and architectural decisions first, and only then bring agents in full-time.
But documentation alone isn’t the whole answer, especially for a project that was originally written by a human, without the specs and architecture decisions to match. You can’t fully reconstruct years of implicit decisions after the fact — some of that understanding only comes back to you by reading the code itself. So alongside building up documentation, I’d add a second habit: keep reviewing the code yourself, even once the agents are doing most of the implementation. Not on every single task — that would defeat the point of delegating in the first place — but at natural checkpoints, say once a meaningful piece of logic is finished. That’s usually enough to catch the moments where an agent is quietly accumulating complexity, and to step in with the kind of precise, implementation-level direction it can’t arrive at on its own.
Word Tracker never went anywhere — it’s been on the App Store the whole time. What’s changed is what’s running underneath: a stack that’s simpler than it’s ever been, and I’m hopeful this finally opens the door to the features existing users have been asking for.
Have you brought an old project back from the dead — with or without AI? I’d love to hear what got you unblocked, or what nearly didn’t. Let’s talk in the comments.
#AI #SoftwareDevelopment #SwiftUI #iOSDevelopment #ClaudeCode #AgenticWorkflows #LegacyCode #AppDevelopment