Client:
Personal project
Timeline:
Ongoing
Role:
Solo product designer, product owner, and builder
Scope:
iOS/Android app (Expo/React Native), a custom prioritization engine, a full design system, built end to end using Claude in chat, Claude Code, and Figma Make
Focus:
AI-native product design and development, technical judgment, prototyping with AI as build partner rather than execution tool
I wanted to test something specific: could I take a product from a rough idea through to real, working, native mobile code, entirely on my own, with AI doing the execution and me doing the thinking. Not a landing page. Not a Figma prototype. An actual app, with a real data model, a real engine, and real bugs.
Grove is what I built to answer that question. It is a calm, capture-first daily planner. You throw scattered tasks, reminders, and half formed thoughts at it. It ranks them by importance and urgency, fits them into a realistic daily capacity, and reprioritizes automatically as life happens, without ever making you feel behind.
The product had to be good enough to actually want to use. That constraint mattered. It is much easier to fake competence on a project with no real user, including yourself. I held myself to the same bar I would hold an engineering team to, and used that bar to test how far AI collaboration could actually go.
I designed the product, wrote every specification, made every architectural and scope call, wrote every prompt, and debugged every failure.
There was no engineer, no designer, and no product manager on this project except me. Claude Code wrote the code. I decided what the code needed to do, reviewed what it produced, caught what was wrong, and made the calls on what was worth fixing and what was worth cutting.
That distinction matters. I am not describing a project where I described an idea and AI built it.
Before a single screen existed, I wrote four documents: a product brief, a prioritization engine specification, a design system approach, and a page flow and information architecture map. These became the single source of truth for the entire build, and I kept them updated as the product evolved.
This was a deliberate choice, not a formality. The original idea was a different app entirely, an AI powered notes app. Working through the spec with Claude, I identified that the concept had real competitive exposure and that the feature list was too large for one person to build and maintain. I pivoted the product to Grove: a leaner, more defensible idea built around one mechanic done well, an evolving daily list that reprioritizes itself as the day changes.
One technical decision from that early spec work has held up through the entire build. The prioritization engine, the part of Grove that ranks tasks and manages daily capacity, runs entirely on deterministic arithmetic. No AI call is required for it to function. The only place an AI call touches the engine is turning a reshuffle into a plain language sentence, and even that is built with a scripted fallback so the app works correctly if that call ever fails. I made that call early, specifically so the product's core mechanic would be fast, predictable, and cheap to run, rather than dependent on an LLM behaving well every time. That is a product and engineering decision, not a prompting decision, and it is the kind of judgment call that has to come from the person directing the build, not the tool doing the building.
I also made a deliberate sequencing call on visual design that's worth naming, since it shapes how the screenshots in this case study should be read. The design system currently in the app is intentionally minimal: a calm, functional palette and type system built to be clean enough that I could evaluate structure and interaction without visual noise getting in the way, and nothing more considered than that. I made the call to prioritize getting the architecture, the engine, and the interaction model right first, and to hold off on real branding, including a proper logo and a finished visual identity, until I'm confident the underlying product is solid enough to be worth designing around. What's shown here is a working scaffold, not a preview of the finished product.
AI is very good at giving you the statistically safest, most common answer. Several times during this build, that was exactly the wrong answer, and catching it was my job.
The clearest example is the logo. I asked an AI image tool to generate an app icon around the idea of a grove, calm growth, quiet structure. It returned a cluster of circles forming a tree canopy. Technically competent, and also one of the most overused visual tropes in the entire calm productivity app category. Half the apps in that space have converged on some version of the same shape, because it is the safest possible interpretation of the brief. I rejected it, explained why to my own reasoning before explaining it back to the tool, and made the call to pause the logo entirely rather than keep iterating toward a mediocre, generic mark. That is a taste call. No tool makes it for you.
The same pattern showed up in smaller product decisions throughout the build. Early on, the daily check in feature had a button that did nothing, a leftover state called "this is plenty" that no longer served a purpose once the interaction model changed. I caught it, cut it, and simplified the interaction to something more direct. When I asked for achievement badges to celebrate milestones, I was explicit that they had to be positive only, no streaks, no guilt mechanics, no visible negative state, because that directly contradicted the calm, non judgmental premise of the product. AI will happily build a Duolingo style streak system if you ask for gamification. I had to specify, explicitly, what kind of gamification was actually consistent with what I was building.
Nine rounds of fixes that were each individually correct, and still didn't work.
Midway through the build, I asked for a small polish item: when a category on the daily list is collapsed, its contents should disappear cleanly instead of overlapping other elements as it closes. This should have been a minor fix. It took nine rounds of investigation to actually solve, and it is the single best example I can point to of what real AI collaboration looks like when the easy answer does not work.
Each fix attempt was genuine and individually correct. Matching animation durations. Locking container and content to a shared animated value. Diagnosing that the visual "vertical blinds" effect was gone because of an earlier architectural refactor, which unblocked an approach that had previously been ruled out. Each of these closed off one real possibility without fixing the actual bug, and each one taught us something true about the system, even while being wrong about the fix.
The eventual root cause was subtle. The row being collapsed was not updating in place, it was unmounting and remounting as a fresh instance during the collapse, and that fresh instance never received the signal that it was supposed to be closing. Four separate fixes to the row's own rendering logic had no chance of working, because none of them addressed a problem that lived one level up, in how React was committing changes to the list. We only found this by adding mount and unmount lifecycle logging and reading the actual sequence of events, rather than continuing to guess.
What this taught me: a fix that is confirmed correct in isolation and still does not resolve the visible bug is a strong signal that the entire mental model of the problem is wrong, not that the fix needs one more adjustment.
Knowing when to stop tuning and ask for real diagnostic evidence instead is not a coding skill. It is a judgment skill, and it is exactly the skill that determines whether AI collaboration compounds into something real or stalls out in an endless loop of plausible sounding patches.
The most useful moments in this build were not the times the AI did what I asked well. They were the times it pushed back.
When I asked for a visually ambitious change to how dragged items resize their containers in real time, Claude Code gave me an honest complexity assessment before writing any code: this is a fundamentally different mechanism than what exists today, here is the specific risk to a feature that already works, and here is a cheaper alternative if the real goal is the feeling rather than the literal effect. I chose to proceed anyway, because I judged the interaction detail was worth the risk given I had already committed a safe rollback point. That is the collaboration model working as intended. The tool gave me a real technical opinion. I made the product call.
Later in the same session, when I proposed a much riskier structural change, restructuring the render tree so list items became children of a true container component, Claude Code explained clearly why that specific version was incompatible with the drag and reorder library already in use, and explicitly recommended against it in favor of a safer version that achieved the same visual goal without the risk. I agreed, and that safer version is what shipped.
I was also struck by its willingness to correct itself in front of me. At one point it presented a theory for a bug, then found direct evidence disproving its own explanation, and said so plainly rather than letting a shaky theory stand. That kind of self-correction is not something I expected from a coding tool. It is something I expect from a good collaborator.
Grove today has a working prioritization engine, a calm capture-first daily list, a full custom design system, categories with configurable active days and recurrence, drag to reorder with live capacity rebalancing, a calendar view distinguishing read only history from editable future days, and a build architecture I understand well enough to keep directing confidently.
Grove is not launched, and I am not presenting it as though it is. The prioritization engine, the interaction model, and the core screens are built and genuinely work well on device.
What remains is real and tracked, not hidden: authentication currently runs on a placeholder, real account backup is not yet built, and app store submission assets do not exist yet.
I think that honesty is more useful evidence than a polished screenshot would be. A finished app tells you I can finish something. A detailed, working, in-progress build with a clear account of every decision along the way tells you how I actually think and work when the tool I am directing does not get it right on the first try, which is most of the time, for any tool, on any project worth building.
The skill that mattered most on this project was never prompting. It was knowing what to ask for, recognizing when an answer was subtly wrong even though it looked right, and knowing the difference between a fix that needs one more adjustment and a fix that means the whole approach is wrong.
Each session on Grove built on the last. The specification documents meant I was never re-explaining the product from scratch. The debugging patterns I learned early, ask for a complexity assessment before a risky change, ask for lifecycle evidence when a fix does not land, batch related changes and isolate risky ones, made every later session faster and more precise than the one before it. That compounding is the real story. Not that AI can build a working app. That a person who develops real judgment about how to direct it gets measurably better at it, session over session, in a way that looks a great deal like any other skill worth having.
A running log, updated as the build progresses. The case study above is a fixed account of the decisions and judgment calls that shaped Grove. This is where I track what's actually happening right now.
Locked the product brief, the prioritization engine spec, the design system approach, and the page flow documentation. Tested the daily opening flow (welcome screen, the main list, reminder handling) as isolated screens before writing any real code, to validate the structure held together before committing to it.
Moved into Claude Code. Scaffolded the Expo project, built the prioritization engine as a standalone, tested module, and reviewed its output against sample data before wiring it into any screen. Built the core navigation and the first working versions of onboarding, the daily list, and capture. Got the app running on device via Expo Go for the first time.
Added configurable active days per category, so a category like Work can exclude itself from weekends automatically. Built drag to reorder for tasks within and across categories, including live capacity rebalancing as items move. This surfaced a deeper structural issue in how categories were rendered, which led to a real architectural refactor rather than another visual patch.
Fixed a rollover bug where incomplete tasks from a prior day weren't correctly carrying forward under certain conditions, and cleaned up the calendar's day-indicator logic so it accurately reflects what's scheduled versus what's just due. Both required tracing actual state changes rather than guessing from the UI.
Added recurring categories with active-day rules, empty-state handling for categories with nothing scheduled yet, and a direct prompt to capture something when a day is completely empty. Wrote this case study.










