Vibe coding in the house of Winchester
Part 1: Building to drown out the voices?
Imagine, if you can, an impossibly large house of 500 rooms, built over a series of decades, to the tastes of an eccentric owner that eschewed the skills of an architect, but instead sought the counsel of a series of skilled tradespeople. You might imagine a fantastical place, with room after room of intrigue and oddity - each only belatedly aligned with the last.
Such a place exists, and it is right in the centre of Silicon Valley, in San Jose, CA! The Winchester Mystery House has held a place in my imagination ever since my family lived nearby for several years - as well as a family connection: my sister had a part time job taking tickets there, doing her part to heighten the sense of mystery!
For those that aren’t familiar, the mansion of Sarah Winchester (dubbed the Winchester Mystery House after her death in 1922) is “renowned for its size and architectural curiosities”, per Wikipedia, and is also the subject of many legends and urban myths, most of which are almost certainly untrue.
The legend that stuck with me as a seven year old was the story of Sarah Winchester, tortured by the thought of all the souls that died at the hands of the Winchester Repeating Rifle (invented by her husband William Winchester), driven to madness and keeping builders busy for decades building room after room, often tearing down a room multiple times before getting it right.
It turns out most of that is a fabrication - apparently she was a quite pragmatic person, and didn’t believe anyone was after her! So, the motivation doesn’t hold up, but the house itself does remain: staircases that lead to nowhere, bricked up windows, and a mansion that you can sense lacks a unifying vision. Impressive on the outside, but it quickly becomes confusing once one starts looking into the details.
Part 2: New tools, old problem
I was recently looking for a project to use as a test bed for vibe coding, and decided to build a web app that helps kind-hearted Discogs users who have friends on the platform that they’d like to gift records to. Obviously, the target audience is me, and the target gift recipient is my brother-in-law who has a massive record collection and equally gigantic wantlist on Discogs. The task was simple: show a view of records that I own, that my brother-in-law wants. And while I’m at it, make a nicer way to view my whole collection from Discogs, because the Collection view leaves a few things to be desired (love you, Discogs! 😘).
Discogs has a somewhat creaky REST API that’s authenticated using OAuth 1.0a (a standard that’s been out of fashion for ~10 years), and their own website has moved on to a newer, not-publicly-documented GraphQL API - so it’s safe to say that Developer Experience for API consumers isn’t top of mind. It is also rate limited to 60 requests per second, but there is no guidance as to whether that’s 60 for the whole application or 60 for each authenticated user. Until I find out, I’m not sharing a link to this site! But I digress.
As one does in the middle third of 2025, I decided to give it a go with v0.dev. I was happy with Next.js as a frontend framework, and I’ve always had a soft spot for Vercel. “Like AWS but friendlier”, I’ve always said to myself. So, I wrote a prompt, faithfully recreated here:
I'd like a responsive web application named Discogs Gifter that I can use to remix views of the data accessible from the Discogs API (https://www.discogs.com/developers). My technical guidelines are:
- Next.js frontend
- API backend so I can create a mobile application at a later time
- Hosted on Vercel
- Provides me the ability to use Discogs' OAuth capabilities, including "sign in with Discogs" redirection, so that I can use my collection and friends list like I can after authenticating with the Discogs site
The capabilities of the application are to:
- Allow me to view a list of items in my discogs collection that appear in my friend's wantlists. This would allow me to gift
- Allow me to view a friend's wantlist with individual variants of a master release that are collapsed down into one single item, summarised with a picture of the album art, the artists names, and master release name, that can be expanded to view the individual releases on my friend's wantlist. This would be used if I'm in a physical store shopping for a gift for my friend
- I would also like a view of my own collection that is expandable, following an Artist->Release hierarchy, with albums listed first, then EPs, etc, in the same order that releases are listed under artist pages on Discogs
Visually, I would like the site to be in the style of Discogs
The chat history shows that v0 thought about my prompt for exactly 6 seconds, and then got to work building this three part site, sitting behind an OAuth Discogs login. And it kind of worked - It even asked me for environment variables to track my client key/secret for Discogs, touche! v0’s preview functionality doesn’t really play well with OAuth, but you can’t win them all - I just deployed straight to Vercel and tested it on the real internet 🔥
I followed that initial prompt up with 40 more, changing/tweaking the app as much as I could, running out of free prompts on v0 multiple times, spiritually committed to vibe coding this thing.
Here’s what worked well:
- It was fast
- It was well suited to the job of developing this specific application, a Next app deployed on Vercel, both from an LLM perspective, and as a tool that deals with deployments and Vercel admin integration
- Front-end components were sufficiently decent looking for my purposes, and prompts to change styling in human English were managed pretty well
- V0 magically figured out how Discogs’ API works, including OAuth and, for the most part, understood the meaning of the fields correctly
Here’s what did not:
- On the odd occasion that I dug into the code view in v0 and tried to make a change, a v0 UI problem nearly always prevented the change from being saved. I presume this was a bug, v0 is still in pretty early days, I guess
- I had a persistent sensation of just being out of control. On numerous occasions, fixing one thing would break another that I’d just gotten right. And aside from a nod at what had just transpired in the code view of v0, it was difficult to gain a holistic view of what had changed in response to my latest prompt
- Eventually I ran out of free prompts, despite my best efforts to ask v0 to do more than one thing at time 😄
So, unwilling to let go of what I’d now call v0.8 of my web app, I ejected from v0 to give it a second life as a full-grown app. I pulled my code from v0 (very easy to do, nice job v0!) into Cursor and created a github repo so I could get my head around what was going on, and start what I now know was the real work: the last 20-30%. 😅
Part 3: The house that Winchester built
Seeing the code for my application in the cold light of Cursor’s dark mode for the first time, I saw what I had created by proxy: a mystery house of my own. Once I saw the parallel, I couldn’t un-see it. Let me bring this parallel to life with the help of some quotes from the Winchester Mystery House Wikipedia entry:
She was known to rebuild and abandon construction if the progress did not meet her expectations, which resulted in a maze-like design.
My code was littered with false starts and doors to nowhere. While there are approximately 4 API endpoints of interest in my application, I had to prune out about 8 superfluous API endpoints from my v0-built application. One key difference between vibe coding and human coding: it seems that cleaning up after yourself is not that “vibey.”
When Winchester died in 1922, the house had 160 rooms, 2,000 doors, 10,000 windows, 47 stairways, 47 fireplaces, 13 bathrooms, and 6 kitchens.
Ok, my parallel here is hyperbolic, but I did end up with 3 pages of an SPA each fetching the same data in different ways, with different caching implementations, and (most annoying) different data structures. So, for example, fixing the way an artist’s name displays across the board was impossible without changing it in 3 places 😢 When vibe coding, forget about DRY, because the code is not written by/for humans.
With plans to expand the farmhouse, Winchester hired at least two architects but dismissed them, deciding to do the planning herself. She designed the rooms one by one, supervised the project, and sought advice from the carpenters she hired.
Two important points I’d like to make here:
- Good for you, Sarah! The difference between the house you own and inhabit vs a piece of software that will almost certainly be someone else’s problem for longer than it is yours should be clear to all. In the cringe parlance of LinkedIn, I “celebrate” Sarah doing her thing on her house, but I would like to “support” people that have inherited software built without any overarching vision or consistency (or, stated in technical terms, without a succinct application architecture).
- The piece of that quote that really gets me is that she “sought advice from the carpenters” - which is the overwhelming feeling I have after looking at this codebase. I am inhabiting a house that was designed by carpenters - expert makers with a very specific remit: wood. Not architecture, or even drywall or windows.
And both of these add up to something important about AI-assisted development tools in general, not just vibe coding, that I've seen emerging as a common view: for any use case that requires longevity, AI-assisted tools aren’t effective unless they’re in the hands of someone capable of a) reasoning with the output and b) knowing what good actually looks like. In other words, the future of our industry seems most likely to sit with human beings that understand fundamentals of computer science, systems engineering, and software architecture. And yes, they’ll probably be using AI-assisted tools to do the more mechanical bits of building applications. For more on using AI-assisted tooling mindfully, do check out Nick Wood's excellent Practical lessons in using generative AI for mobile development.
So, I’ve set to work tearing this application apart and putting it back together - this time using Cursor and proper source control, which affords me the ability to more incrementally see what’s changing and whether I’m happy with it. Even with this approach, I’ve had to walk back entire sequences of chat messages, where Cursor has gone rogue and changed loads of stuff that wasn’t relevant, or kept changing values that I’d manually set. But at the end of it, I always have a line by line diff of what’s changed to approve/deny.
And slowly it’s gotten better, like how all software development used to be. In terms of time, I probably spent 2 days with v0, and 2 weeks with Cursor (nights and weekends, obvs I have a day job) in order to get it to a place that I’m happy to show it off to the occasional fellow record nerd.
Now I just have to vibe code a more aggressive caching strategy to lessen the impact of the API rate limiting, and then I can share the URL with the world! 😜