612 Commits in 30 Days: What Building a Production App With AI Actually Looks Like
There's a genre of tech content right now that goes something like: "I built an app in a weekend with AI." The implication is that coding is now trivial, that software development has been reduced to prompting, that anyone can ship production software before Monday.
I did build a production app with AI. It took 30 days, not a weekend. It's 612 commits as of this writing. I didn't write those commits. I managed them.
The Setup
Worry Jar is a personal journal app with end-to-end encryption, AI-powered insights streamed in real time, and paid tiers via Stripe. It's a React frontend with a .NET 10 backend, deployed on DigitalOcean with CI/CD that pushes to separate dev and production environments on every commit. It's been live at worryjar.com since early March.
I built it with Claude Code, Anthropic's CLI tool. AI wrote the vast majority of the code. But saying "AI wrote it" misses what actually happened — the same way saying a general contractor "built" your house misses the point. The value wasn't in the hammering.
What Each of Us Brought
My background is backend development — data pipelines, API design, database schemas, system architecture. I had a clear picture of how I wanted the services structured, how encryption keys should flow through the request lifecycle, what the API contracts should look like.
What I don't have is frontend design experience. I can tell you whether something looks right, but I couldn't tell you the Tailwind classes to get there. I've never built a rich text editor. I've never wrangled CSS scroll anchoring.
The AI filled in both sides — implementing the architecture I had in mind and making design decisions I wasn't equipped to make. When I said "I want the journal entry to stream AI insights in real time via SSE," it wrote the controller, the streaming hook, the markdown renderer, and the loading states. When I said "this looks too clinical, make it warmer," it adjusted the color palette and typography in ways I wouldn't have known to try.
The dynamic wasn't "I tell it what to type." It was closer to managing a collaborator who's faster than you at execution and better than you at some things, but who doesn't have the full picture of where the project is going.
The Autoscroll Saga
If you want to know what AI-assisted development actually feels like, look at autoscroll.
The concept is simple: when the AI streams a response, the page should scroll down to follow it. Like a chat app. Every messaging product in the world does this.
It took over 20 commits to get right.
The first implementation used scrollIntoView. That broke on mobile Safari. We switched to ResizeObserver. That fired during CSS transitions and disengaged the auto-scroll. We added a grace period. That caused a bounce effect. We switched to a sentinel div. That stopped too early. We capped scrolling at the insight heading. That used a hardcoded margin that didn't account for the mobile address bar. We read visualViewport.offsetTop. That finally worked — until images loaded and shifted the layout.
The AI wrote every one of those fixes. But it couldn't feel the scroll stutter on an iPhone 17 — that feedback loop was mine. I'd test on my phone, describe what was wrong, and it would generate the next attempt. Sometimes the fix worked. Sometimes it introduced a new bug. We'd go again.
This pattern repeated across the project. Auto-focus on the text editor? Fifteen commits. iOS Safari input zoom? Five commits and two completely different approaches. Share link UI alignment? Four rounds of tweaking.
The AI gets you to 80% almost instantly. The last 20% is where you both earn it.
The Duplication Problem
One thing I kept running into: I'd ask for a change to one component and the AI would implement it perfectly — in that one component. Three other components with the same pattern would stay unchanged.
This makes sense if you think about it. The AI is working on what you asked it to work on. It doesn't carry a mental map of everywhere a pattern appears across your codebase the way you do after weeks of living in it. So I'd fix the share UI in one place, then notice the History page still had the old version. Fix the autoscroll behavior on Journal, then realize Reflect had the same bug.
This was the most consistent source of follow-up commits. Not bugs in the AI's code, just incomplete propagation. The fix was getting better at saying "this pattern also exists in X and Y" — but honestly, I missed it plenty of times myself and only caught it later while testing something else.
Architecture and Knowing When to Push Back
Early on, the AI suggested patterns that worked but weren't quite right structurally. Services with too many responsibilities. Encryption logic coupled too tightly to the controllers. A pattern analysis feature that re-decrypted every entry on every request instead of batching.
These are the kinds of things that are fine at commit 50 and painful at commit 300. My backend experience helped me spot them, but it's worth being honest: the AI also suggested good architectural patterns I wouldn't have reached for — organizing the streaming logic into reusable hooks, splitting state management to avoid redundant re-renders. It went both ways.
One thing that helped was a context document describing the architecture — database schema, API contracts, encryption flow, design conventions. The AI read it at the start of every session, and I had the AI keep it updated as the project evolved. The better that document was, the better the output. Garbage in, garbage out applies to AI collaboration as much as anything else.
Where the AI Was Better Than Me
The design work. This is where I expected to struggle most, and instead it became the smoothest part of the project.
The sage green color palette? AI suggestion. The Fraunces serif font? AI. The dark mode color tuning — shifting from warm hues to cool blue? I said "this doesn't feel right in dark mode" and it adjusted the hue angle in oklch color space. I didn't even know oklch was a thing.
The streaming UX is another example. The raw server chunks came in bursts — a few words, then nothing, then a paragraph all at once. It felt terrible. I asked the AI how other chat products handle this, and we landed on a drip-feed buffer that releases text at a steady ~80 characters per second. A small thing, but it's the difference between "janky prototype" and "polished product."
I came in thinking design would be my weak point. It ended up being one of the smoothest parts, partly because of a Claude Code plugin called Impeccable that's specifically built for frontend design quality. Between that and the base model's knowledge of CSS and color theory, I could focus on "does this look right?" and let the tooling handle the implementation details.
The Math
I'm not going to pretend I tracked this rigorously, but roughly: a lot of features went in clean on the first or second try. Billing, encryption, the chat interfaces, export — describe what you want, review the code, ship it. A chunk of features needed a few rounds of back and forth to get right, usually around edge cases or mobile behavior. And then some features — autoscroll, the rich text editor, iOS Safari anything, media attachments — turned into multi-day grinds where most of the commits were fixes on top of fixes.
The total time was about 30 calendar days, probably 1-2 hours per day on average. Without AI, this project would have taken months — not because the code is especially hard, but because the sheer volume of implementation work would have killed my momentum long before I got here.
What AI changed wasn't the difficulty ceiling. It was the activation energy. Ideas that would have stayed in my head — "what if entries had image attachments with encrypted storage?" — became afternoon projects instead of week-long endeavors. The gap between "that would be cool" and "let me try it" basically disappeared.
What This Means
The interesting question isn't "can AI write code?" It obviously can. The interesting question is what the human role becomes when the typing is no longer the bottleneck.
From this project, the answer seems to be: you become the person who holds the full picture. You know what the project is supposed to feel like. You know which architectural shortcuts will cost you later. You test on real devices and notice the thing that's slightly off. You remember that the same pattern exists in four other components. You maintain the context document that makes the AI effective in the first place.
None of that is glamorous. It's not "prompt engineering" or whatever the current buzzword is. It's closer to what a good tech lead does — set direction, maintain standards, unblock the people (or tools) doing the implementation, and catch the things that fall through the cracks.
I didn't write 612 commits. I managed them — sometimes well, sometimes not. The AI did things I couldn't have done (the design work, the sheer velocity) and I did things it couldn't have done (feeling the scroll jank, knowing which abstractions would hold up). Between the two of us, we shipped a production app in a month.
That's what building with AI actually looks like. Not magic, not replacement. A collaboration where both sides are doing real work.
Back to blog