In my last post, I wrote about what building with AI actually taught me — how the constraint has shifted from ‘can we build this?’ to ‘should this exist at all?’
This one is about what the build actually looked like.
Over roughly 30 days, I built GeoSheet: a spatially-aware spreadsheet that lets you work with geographic data the same way you work with any other data — without GIS software or specialized skills. Real-time collaboration, a custom formula engine, an AI agent that can read and write data, authentication, billing, and deployed infrastructure.
Not a prototype. A production system.
Here’s what it actually looked like to build.
The Build Model Changed, But Not in the Way I Expected
The core loop was simple: describe what I wanted, have AI generate an implementation, review it, correct it, repeat.
I ran roughly 195 of these sessions over about six weeks — sometimes under an hour, sometimes longer, each with a clear objective. Think of them less like traditional sprints and more like focused working sessions with a very fast junior engineer who never gets tired.
What became clear quickly is that AI wasn’t replacing development. It was compressing execution.
It could generate working code quickly, often across multiple files. But it didn’t decide what should be built or how those pieces should fit together. That still required judgment.
The speed came from how quickly things could be implemented. The direction still came from me.
Using Multiple Agents Changed Something I Didn’t Expect
It also wasn’t just one AI tool. Claude Code was the primary implementation tool. In later sprints, I also used Devin for code reviews and Cursor as an occasional second opinion on refactoring and architecture questions.
This turned out to be more valuable than I anticipated — but not for the reason I expected.
The moments when the tools disagreed were the most informative. Not because one was right and one was wrong, but because the disagreement surfaced assumptions that had been invisible.
In one case, Claude Code and Cursor gave meaningfully different approaches to how state should flow through the collaboration layer. Working through why they differed forced a clarity I wouldn’t have reached by just accepting the first answer.
Using multiple agents in complementary roles reduced blind spots. But it also introduced a new operational reality: AI doesn’t remove coordination. It changes where coordination shows up.
Once you have multiple agents, multiple branches, and separate review flows, keeping track of what is actually in progress still requires structure.
Architecture Decisions Mattered More, Not Less
One of the more important realizations: architecture didn’t become less important with AI. It became more important.
When building is slow, you have time to rethink decisions. When building is fast, decisions propagate immediately.
A few early choices paid off significantly.
GeoSheet’s grid is rendered using HTML Canvas instead of a traditional DOM-based table. For a spatial spreadsheet rendering large datasets alongside geographic overlays and live presence cursors, that decision was essential — DOM-based rendering would have collapsed under the load. The trade-off was increased event-handling complexity, but it was the right call.
Real-time collaboration is handled using CRDTs via Yjs. That effectively removed an entire class of synchronization problems. Multiple users can edit concurrently without conflicts, and the system resolves them automatically.
State management naturally splits into three layers: synchronous UI state, collaborative data, and server-fetched metadata. That separation wasn’t designed upfront — it emerged after running into consistency problems. Once the boundaries were clear, a whole category of bugs disappeared.
None of these decisions was made by AI in isolation. They came out of a back-and-forth. AI would suggest approaches, I would evaluate them, and we’d commit to a direction. That collaboration worked well — but it didn’t remove the need to think ahead.
Where AI Was a Clear Multiplier
There were areas where AI was consistently valuable.
Scaffolding new functionality became almost trivial. API routes, components, migrations, test files — from real effort to minutes.
Refactoring was another clear win. Updating logic across multiple files — tedious and error-prone by hand — became faster and more reliable.
Test generation was surprisingly effective. Given a function and a description of expected behavior, AI could produce meaningful coverage, including edge cases that weren’t immediately obvious.
In these areas, the productivity gain was real and significant.
Where AI Didn’t Help
There were also areas where AI didn’t meaningfully reduce the work.
Product decisions remained entirely human. Deciding what to build, what to prioritize, and what tradeoffs to make still required context and judgment that couldn’t be delegated.
UX was similar. AI could generate interfaces that looked good individually, but not necessarily feel cohesive together. It was easy to end up with a collection of individually reasonable components that didn’t quite fit as a product.
Production issues were another category. Problems involving infrastructure, credentials, or networking required understanding the actual environment. AI could assist in reasoning through options, but it didn’t replace that knowledge.
And coordination remained stubbornly human. Someone still needs a coherent view of what’s in progress, what’s waiting for review, what’s merged, and what’s changed direction. Faster execution doesn’t remove that responsibility.
Context Became the Real Lever
One of the biggest shifts occurred once the project reached a certain level of complexity.
Early on, I didn’t use formal specs. That worked while features were contained.
But as more systems were added — collaboration, AI tooling, billing, APIs — it became necessary to introduce structure. I wrote a set of specification documents and maintained a CLAUDE.md file that described the system, conventions, and known issues — often iterating on them in collaboration with AI. I also kept a memory.md for things that had caused problems before.
These became critical.
Without them, each AI session would effectively have to start from scratch. With them, each session builds on accumulated context.
Documentation became the system’s memory layer.
For anyone attempting a build like this: that’s not a nice-to-have. In a multi-agent workflow, shared context is the only thing keeping the work coherent. The time you spend writing it down is paid back immediately, every session, for the rest of the project.
Speed Doesn’t Remove Problems — It Compresses Them
Moving quickly didn’t eliminate common issues. It made them show up faster.
- Inconsistent data modeling: I allowed different representations for spatial data types early on. That seemed minor at the time. It created compounding complexity as more features were built on top of it.
- Design consistency: Without an early, defined design system, UI inconsistencies accumulated. Fixing them later was more expensive than establishing the standard upfront.
- Testing gaps: even with solid unit and end-to-end coverage, gaps remained — especially around how different parts of the system interacted. Manual QA still played a role.
AI didn’t introduce any of these problems. But it accelerated their spread.
The Constraint I Didn’t Expect
One surprise wasn’t about development at all. It was about the product itself.
GeoSheet’s AI assistant handles multi-step operations — geocoding a list of addresses, building a chart from scratch. Each step requires a round-trip to the model.
A 10-step operation can easily translate into 20–30 seconds of perceived waiting.
We reduced some of this through batching and prompt tuning, but the core constraint remained.
This isn’t an application problem — it’s a model constraint, and it has direct implications for how AI-driven experiences need to be designed.
Latency isn’t just a technical issue. It’s a product design problem that has to be solved at the interaction level, not the infrastructure level.
What I’d Do Differently
A few things would change if I were starting again.
Establish a design system from the beginning. Enforce consistent data formats from day one. Introduce end-to-end testing earlier. Set up a staging environment before going to production.
And formalize coordination earlier. Once the work spans multiple agents, multiple branches, and multiple review loops, execution speed is no longer the only thing to manage. Coherence becomes its own problem to solve.
None of these are new lessons.
What changed is how much faster the consequences arrive when you get them wrong.
Final Thought
AI enables faster development than ever. But it doesn’t change what matters.
Architecture still matters. Product judgment still matters. UX still matters. Coordination still matters. QA still matters.
If anything, they all matter more — because when execution is no longer the bottleneck, the real constraint becomes deciding what should exist, how it should fit together, and how to keep the whole system coherent as it evolves.
That’s the job.