About a week ago, I decided to replace my Wordpress blog with a custom built platform running on Azure.
Not as a long term rewrite, not as a side project, and not as an architectural exercise. This was very deliberately a vibe coding experiment. Minimal upfront design, fast iteration, heavy use of Copilots, and a willingness to see where things broke.
A week later, the site is fully live, serving 169 migrated posts on preserved URLs, with newsletters, comments, likes, admin tooling, RSS, sitemap, and search engines already crawling the new platform.
That is both the success story and the warning.
How the early decisions were really made
In practice, the choices were far less deliberate than they might sound. Copilot drove much of the early direction, and only later did the consequences of those suggestions become obvious.
Static Web Apps is the best example.
GitHub Copilot repeatedly recommended Azure Static Web Apps for deployment, even though it already had full context that the site used server components, API routes, admin functionality, and incremental regeneration. On paper, Static Web Apps looks like the modern default for Next.js, and that bias clearly came through.
In reality, it was a poor fit.
The real breaking point was not abstract framework compatibility, it was content ownership. Static deployments overwrite the running site on every build. That meant any new content created at runtime would simply disappear the next time GitHub Actions ran.
That behaviour, not theory, forced the move to Azure App Service.
Exactly the same logic later applied to content storage. Initially, article content lived as JSON committed to the repo. That works right up until you allow runtime mutation. On managed platforms, the filesystem is ephemeral, and deployments happily replace whatever was there before.
At that point, moving all mutable data into object storage was not an architectural preference, it was the only sane option.
Build and deployment were where vibe coding hurt most
This is where the experiment became genuinely uncomfortable.
GitHub Copilot was excellent at scaffolding the application itself. Routing, components, data access, TypeScript types, and layouts came together very quickly.
Build and deployment did not.
Copilot consistently struggled with managed deployment specifics. It suggested broken workflows, deprecated approaches, and pipelines that caused the platform to rebuild already packaged artifacts. Platform specific guidance tools didn’t help much either. They understood individual services, but struggled to reason about why standalone builds kept failing at runtime.
Several hours were lost to pipelines that looked correct, deployed successfully, and then failed the moment the app tried to start.
The breakthrough came when I stopped following generated guidance and went back to actual documentation. Once the correct deployment pattern was clear, disabling automated builds, deploying a pre built standalone package, and explicitly defining the startup command, things stabilised quickly.
At that point, another Copilot became genuinely useful again, but not as a source of invented solutions. I used it to sense check approaches, generate explanations, and interpret what the documentation was actually saying. Those outputs then fed into the code focused Copilot, which is far better at turning clear, well framed instructions into working implementations.
What emerged was a slightly odd but effective AI to AI development loop. One Copilot grounded decisions in documented platform reality, while the other handled the mechanical act of implementation. Used together like this, they were far more effective than either was on its own.
The broader lesson is an important one. AI is very good at producing plausible pipelines. It is still very bad at knowing when managed platforms need to be told, very explicitly, to stop being helpful.
Vibe coding still massively compressed the timeline
Despite all of that, the outcome matters.
If I had built this platform carefully, defensively, and manually from day one, it would not have taken six to eight hours. It would have taken days.
The application itself, not the deployment, came together remarkably fast. Preserving legacy URLs, migrating 169 posts, implementing SEO features, newsletters, comments, likes, and admin tooling would normally be a serious chunk of work.
But it is important to be explicit about what actually happened here.
I did not write code.
I instructed, informed, ordered, corrected, and occasionally shouted at the AI. It wrote the code. My role was to hold intent, maintain coherence, validate assumptions, and intervene when something that looked correct was operationally wrong.
When it flowed, it felt almost frictionless because I stayed in a continuous decision making loop. I didn’t have to drop out of context to manually implement changes. When it stopped flowing, it was almost always because build and deployment are not forgiving domains, and the AI was confidently guessing.
That is where most of the time went, not in building features, but in dealing with the reality of managed runtimes, opinionated build systems, and platform behaviour you only understand once things break.
Ignoring my own controls, and why that mattered
One interesting side effect of this experiment only really became obvious afterwards.
I ignored almost all of the controls and processes I normally rely on when doing this kind of work at enterprise scale. There was no formal framing, no structured intake, no scoring models, no dashboards, checkpoints, or governance overlays. None of the mechanisms I would usually insist on when multiple teams, shared ownership, or long term accountability are involved.
And yet, I still ended up with a solution I am mostly happy with.
That does not mean those controls are unnecessary or wrong. It means they exist for a different problem space. Those mechanisms are designed for shared ownership, long lived platforms, multiple contributors, auditability, and political safety. This project had none of that complexity. The blast radius was small, the stakeholder list was short, and the tolerance for rough edges was deliberately high.
What this reinforced is that governance is situational, not universal. The right level of process depends far more on risk and scope than on how sophisticated the tooling is. In this case, speed and learning mattered more than formal control, and accepting that trade off consciously turned out to be the right decision.
That distinction matters, especially when people talk about scaling vibe coding into enterprise environments. The mistake is not in having controls, it is in assuming the same controls apply equally to every context.
The honest pros and cons of vibe coding
The upside is obvious. In under a week, and realistically under a working day of effort, I now have a custom publishing platform that I fully own. I understand where the data lives. I control how it evolves. There are no plugins, no hidden state, and no rented features waiting to break.
The downside is equally clear. Build and deployment logic is not something you can safely hand over to generated guesses. Copilot optimises for common patterns, not for platform truth. When it is wrong, it can be confidently wrong, and you will burn time until you reassert control.
Vibe coding is not about switching your brain off. It is about moving judgement upstream and using AI as an implementation engine, not an authority.
Would I do this again?
Yes, without hesitation, but with very clear boundaries.
I would vibe code the application layer exactly the same way. I would not vibe code the deployment layer without grounding it in authoritative documentation first. That part demands intent, sequencing, and an understanding of how platforms actually behave under mutation.
What this exercise really showed is not that AI removed engineering effort, but that it relocated it. I did not write code at all. At no point did I sit and implement functions, components, or pipelines by hand. Instead, my role was to instruct, inform, redirect, and occasionally argue with the AI until the system behaved correctly.
The work moved upstream. Framing problems. Validating assumptions. Calling out when something looked right but was operationally wrong. Knowing when generated advice was plausible versus when it contradicted platform reality.
The AI wrote the code. I owned the decisions.
That shift matters. It explains how this was achievable in six to eight hours instead of several days, without pretending the effort vanished. It didn’t. It changed shape.
That is real progress, just not the kind that lets you switch your brain off.
A final thought, and an invitation
I am mostly happy with where this landed, but it is very much a product of the trade offs and constraints I consciously chose. There is a backlog, there are known rough edges, and that is intentional.
If you read the blog regularly and something feels awkward, confusing, or just slightly off, I would genuinely welcome the feedback. Not as a bug report or an architecture review, but as a signal. Vibe coding lives or dies on how things feel to real users, not just whether they technically work.

