ToDo When Nothing Else Existed
Why this app had to exist, and why rebuilding it matters now
When I first built ToDo, my goals went beyond simply tracking tasks. I needed a tool that would help me remember the things that mattered in my day-to-day life, and at the same time I wanted to stretch into more advanced areas of iOS development. Guess Animals! was my first exploration into structuring an app and understanding feedback, but ToDo was meant to be a bridge into architectural complexity; models composed with multiple relationships, dynamic lists, persistent storage that felt natural and real, and interactions that hinted at apps becoming larger in scope. In the background was a vision of using this app as a foundation for something even broader, something that could grow with real workflows rather than remain a playground or a demo.
Now the app stands at a crossroads. It still launches, and its interface still feels familiar, but it also reflects the passage of time in the platform. Swift, SwiftUI, and SwiftData have evolved significantly since the last release, and, with those changes, the assumptions baked into the original implementation no longer hold. The app becomes fragile on modern versions of iOS and its sister platforms. Crashes show up unpredictably, not because there is something inherently wrong with the idea of a to-do list, but because the app was assembled in service of learning, without a firm architectural foundation built for longevity, leaving it ill-equipped for the system it now runs on. What once worked has been revealed to be brittle, and that brittleness is a function of decisions made at the outset as well as blind spots in how system evolution was accounted for.
The app becomes fragile on modern versions of iOS and its sister platforms. Crashes show up unpredictably, not because there is something inherently wrong with the idea of a to-do list, but because the way the app was assembled — in service of learning, without a firm architectural foundation designed for longevity — leaves it ill-equipped for the system it now runs on.
There is a rhythm to how software ages, especially on platforms that change every year. Some code continues to hum along without flinching; other code becomes reflective of its own construction, exposing seams and weak points as the system moves beneath it. This distinction between stability and fragility is not accidental. It is a consequence of how responsibilities were assigned, how state was modeled, and how control flowed between components. In an app like ToDo, with multiple models, lists, and interdependent views, those decisions ripple outward. They expose themselves during everyday use and they become impossible to ignore when the operating system interprets state differently, when frameworks deprecate behaviors and crash into each other, or when event loops and lifecycle semantics evolve just enough to make previously hidden assumptions collapse.
Some code continues to hum along without flinching; other code becomes reflective of its own construction, exposing seams and weak points as the system moves beneath it.
Fixing the app, therefore, cannot be a superficial update. It requires reconsidering how data and view hierarchies are managed in ToDo. It requires embracing the modern language, its features and frameworks, that Apple has introduced; and it requires modeling state in ways that reflect current expectations rather than outdated habits. Rewriting ToDo offers a chance to build with Swift 6 syntax that feels both expressive and clear, to use SwiftUI 6 in ways that respect its design intent rather than contort it into patterns that once felt familiar, and to leverage SwiftData in a way that aligns persistence with the mental model of the app rather than treating storage as an afterthought.
At the same time, it is important to recognize that this rebuild is not merely a technical exercise. It is a continuation of a personal journey that began with that first tap into iOS development. ToDo exists because it was useful to me in the first place and because it pushed me to think beyond beginner patterns. The fact that it now demands a rewrite is not a failure; it is a reflection of growth, of platform change, and of the complexity inherent in real software. Speaking plainly, this rebuild is about responsibility, one much overdue at this point. It is about acknowledging where assumptions have aged poorly and taking charge of how a system behaves rather than hoping it continues to behave at all.
In practical terms, the older version of ToDo was constructed without clear architectural boundaries and without a disciplined separation between model logic and user interface.
In practical terms, the older version of ToDo was constructed without clear architectural boundaries and without a disciplined separation between model logic and user interface. It blended concerns in ways that felt natural at the time but now reveal themselves as sources of fragility, where the cracks are. Multiple models were composed without a shared understanding of invariants. State mutations were sometimes spread across views rather than centralized. Queries and updates to persistent storage happened in contexts that did not anticipate how SwiftData and the lifecycle of views would evolve over time. These patterns are common in early apps and reflect real paths that many developers traverse as they learn, but the product of that learning is not always something that holds up under sustained use or platform evolution.
A recompilation under a newer SDK alone cannot fix these structural concerns. The rebuild requires us to think in terms of intent rather than reaction. Where previously the goal was to make something that worked, the goal now is to make something that lasts, something that integrates with the operating system’s expectations rather than fights them. That means rethinking data flow in the app with intentional architecture, introducing clear ownership boundaries for state, and embracing the patterns that modern Swift development encourages. It also means leaving behind strategies that feel convenient in the moment but accumulate technical debt over time.
The rebuild requires us to think in terms of intent rather than reaction.
As we embark on this series of posts about ToDo’s rebuild, this article is meant to orient you to what the app is, why it matters, and why a structural rebuild is both necessary and valuable. In time, I will dig deeper into the specific architectural shortcomings that led to fragility, and will then walk through the concrete steps taken to address those issues. I will include explanations of what modern SwiftUI and SwiftData patterns look like in a real app, how data structures should align with persistent models, and how state can be propagated in ways that avoid cascading crashes or inconsistent behavior.
Understanding why an app breaks when frameworks or system expectations shift is itself a high-value lesson. It is easy to assume that updating language syntax or replacing deprecated APIs will solve all problems, but in practice it is the deeper architectural decisions that determine whether those surface changes are sufficient or merely cosmetic. In the case of ToDo, a superficial update would be akin to replacing the paint on a wall with crumbling plaster beneath. The rebuild must address the foundation.
Next time, I will examine what was wrong in detail, identifying how the existing design leads to instability, how certain interactions expose weaknesses in state management, and how multiple models are coupled in ways that increase fragility. That analysis will lay the groundwork for the rebuild itself and will provide context for the solutions that follow.
Rebuilding an app is never just about fixing what is broken. It is about rediscovering what matters in the way a system is composed and lived with. ToDo’s next chapter begins with intention, clarity, and an explicit acknowledgment of what it must become to serve its users, both present and future.


