← BACK TO THE FEED
DISPATCH #58NextjsFoundryFrontend

A Portfolio That Grew Into a Blog: Rebuilding on Next.js

A Portfolio That Grew Into a Blog: Rebuilding on Next.js

Discover how I transformed my static portfolio into a server-side rendered blog using an AI-orchestrated fleet. I detail the architecture, the governance layer, and the surprising economic reality of using multi-agent workflows for framework migrations.

tedward.net did not start life as a blog. The first version was a portfolio, my CV in website form, a tidy place to point people at my experience and move on. Then, about a year ago, I found I actually wanted to write: to talk about the tech I was working with and the shape of my career, not just list it. So I bolted a blog onto the portfolio, and over the following months the writing quietly became the point. The site had grown into something its architecture was never designed for.

Because that architecture was a Vite single-page app. It was fast, it was mine, and for a portfolio it was perfect. But a client-rendered SPA has a hard ceiling for a blog, and I kept walking into it. Every page arrived as a blank shell until JavaScript booted, which meant crawlers saw almost nothing and, the part that actually stung, links to my posts unfurled as naked URLs in iMessage, Slack, and LinkedIn. No title, no image, no context. For a site whose whole new purpose was to be read and shared, that is an own goal.


The Case for a Rebuild

I had known the fix for a long time: rebuild on Next.js, a framework that renders on the server so the first byte a machine receives is the actual page. I had also known, roughly, what it would cost me, a month or so of evenings and weekends to recode the thing properly, which is exactly why I never did it. The site worked. A month of my own time to fix an SEO problem on a personal blog is a hard sell to yourself.

Two things changed my mind at once. The first was Bun. I actually caught wind of it on social media, the team openly floating the idea of moving their entire engine from Zig to Rust, orchestrated with AI agents, long before the detailed write-up that only landed recently. Even that early exploration was enough to reset my sense of scale: a job I had been sizing in weeks might now be a job of days. The second was the model that made their rewrite work, Claude Fable 5, which had just arrived, included, in my existing plan. The recode I had been putting off for a year suddenly cost me almost nothing to attempt.


What v2 Actually Is

The rebuild, I have been calling it v2, moves the whole site onto the Next.js App Router running on AWS Amplify. The architecture shift is the point: pages are Server Components rendered ahead of time and revalidated on a schedule, so the site is fast and legible to machines. Concretely, that unlocked the things the SPA never could:

  • Real link previews: Every page now emits proper Open Graph and Twitter metadata, and each one gets a share card generated on demand from the site's own design language, no more naked URLs.

  • An actual feed: There is a real RSS feed again, and permanent redirects so none of the old links rot.

  • Privacy-first analytics: I wanted to know which posts land without becoming the surveillance I dislike on other sites, so v2 ships a cookieless, no-PII tracker with a small admin dashboard.

  • A brand-new concierge: Ask the Archive is an entirely new feature this rebuild. It is an AI assistant that knows my work and answers questions about it.


The Twist: I Orchestrated It, I Did Not Type It

I did not hand-write most of v2. I orchestrated it. Rather than sitting in the editor for weeks, I stood up a small workforce of specialised AI agents, each with exactly one job and no permission to stray outside it. Treating AI as a managed workforce rather than a chatbot is a theme I keep returning to, and this migration was the largest test of it yet.

Splitting the work this way is not busywork. A single agent asked to write code, test it, and judge its own design will quietly grade on a curve. Separate agents with separate incentives catch each other's mistakes. The fleet looked like this:

  • The coder: Takes a precise brief and writes production code.

  • The test-writer: A separate agent whose only concern is coverage, writing the co-located unit tests.

  • The design-qa: Compares what actually rendered against the design spec and reports discrepancies.

  • The reviewer: A heavier model acting as the review gate.

  • The orchestrator: The conductor that sequences the others and holds the plan.

For example, a typical interaction for a new component follows a strict flow:

// Example of a validated agentic workflow step
async function createComponent(brief: Brief) {
  const code = await coder.generate(brief);
  const tests = await testWriter.generate(code);
  const report = await reviewer.audit({ code, tests });
  
  if (report.passed) {
    await orchestrator.commit(code, tests);
  } else {
    await coder.refine(report.errors);
  }
}

The Foundry: Governance, Not Vibes

A fleet of agents without governance is just a faster way to make a mess. This is exactly the problem The Foundry exists to solve. The silent killer of agentic work is Context Drift, where an agent slowly loses the thread of the original intent as a task unfolds. The Foundry is the governance layer that keeps every agent aligned with the project's architectural constraints.

For this migration, that meant every agent, on every task, worked inside the same guardrails. I implemented strict inward-only layering rules, where the app layer may lean on data and domain code, but never the reverse. I also enforced a hard no remote compute flag that stopped agents reaching for infrastructure they had no business touching.


The /usage Reckoning

Here is the honest confession: I barely looked at the meter while I was building. I was heads-down directing the fleet, and the token cost stayed an abstraction I happily ignored, right up until I finally ran /usage and saw the size of what I had been running. Over about two days of building, the models took in around seven and a half million tokens and generated about 1.6 million tokens back out. That is the number that matters, and it is smaller than you would guess.

Caching is why it stays that low. On a long task, most of what flows through a model is not new work at all: it is the same standing context replayed on every single step so nobody ever loses the thread. That replay is billed at a fraction of fresh input. Priced at raw pay-as-you-go API rates, /usage reckoned the whole migration would have run about $560. For a full framework migration, shipped in about two days of work, that is a number I would take every single time against the contractor-weeks the same scope used to cost.

The lesson landed backwards, which is the truthful version. I did not diligently watch /usage and optimise as I went; I ran it at the end and let the numbers reframe how I think about this kind of work. Cheap, replayed context is exactly what makes a governed fleet possible, but it is not free, and it is completely invisible unless you go looking.

Here is the honest asterisk, though. That $560 is the number precisely because it never actually left my account, it is the metered API cost the same work would have carried on pay-as-you-go, and if I had been staring at that meter I doubt I would have pressed go for a personal site that already worked. Bundled into my plan, it read as zero, and zero is a very different prompt than five hundred and sixty. I say that not to diminish the result but to be straight about the economics that made me start: the honest figure and the figure I paid are not the same, and pretending otherwise would be the kind of thing this whole post is trying not to do.


Radical Ownership, Reissued

The point of all this was never just to say that AI wrote my website. It was about ownership. I own the architecture, the constraints, the review gates, and the final commit. The agents are a workforce operating inside a system I designed, a system that made a full framework migration something I could direct in a fraction of the time, without lowering the bar on tests, design fidelity, or correctness.

v2 is the result. Same voice, same weekly cadence, but now built on foundations that render on the server, share properly, and were assembled by a governed fleet rather than a lone developer grinding through boilerplate. More on the individual pieces, the share cards, the hardened assistant, and the analytics, in the weeks to come.

END OF DISPATCH