Back to blog

Part 1 of 3 · From Hardcoded to Headless

  • Engineering

The framework pivot that became a tweak

Discover the real story behind a modern marketing site's transformation from a hardcoded Astro project to a headless, CMS-powered platform. In this in-depth post, you'll learn why framework choice isn't just about developer preference or the latest tools, but about balancing speed, performance, and the new reality of AI-amplified development.

Sebastian Piott10 min read

Where we started

We recently moved our marketing site, the one that you are currently on, from a hardcoded Astro project on a custom AWS setup to Netlify, now powered by a headless CMS. This article isn’t about the hosting or the CMS. Instead, it’s about the decision we had to make first: which framework, if any, should power ten mostly-static pages and a new blog feature. The second part is about hosting. The CMS will be discussed in part 3.

I’ve spent more than eight years working with Vue. I believe it’s the framework most developers prefer. Its reactivity model is easy to understand, single-file components keep everything organized, and the official solutions for routing or state management are straightforward, so you don’t have to spend hours comparing options.

Every application at PlayAI is React.

This wasn’t about personal preference. What we’re doing at PlayAI is AI-amplified development, our process integrates AI deeply into development itself, not just for generating code samples or automating routine tasks. We rely on AI models to accelerate prototyping, refactor components, and surface bugs earlier. This approach means the frameworks we choose must support, not limit, the effectiveness of AI as a true development partner. Web-Bench, a benchmark from ByteDance, measures this model performance across frameworks by presenting the same 50 projects with 20 dependent tasks to an LLM-based coding agent. The agent's ability to complete each task is used as a measurable indicator of practical model effectiveness, with output quality, accuracy, and speed tracked for each framework. (Xu et al., 2025) React-based Next outperforms Vue-based Nuxt. (Pati & Zaki, 2025) The reasons are what you’d expect. React is the most widely used UI framework, so it provides the largest training set, and JSX combines markup and logic in one file, making each token more informative for a model. (Most used web frameworks among developers 2025, 2025)

I want to be clear about what this argument means and what it doesn’t mean, because saying “we picked the framework the robot likes” usually gets an eye roll.

This isn’t a claim that React is better designed. The same benchmark shows that Vue and Svelte, which use templates closer to HTML, sometimes outperform React on certain models. (Putra et al., 2025, pp. 355-364) It also points out that Next’s API stability isn’t great across versions. Plus, these results are just a snapshot, the gap depends on the training data, which changes over time.

What I am saying is that we’re dealing with a constraint that matters right now. For us, the time between having an idea and getting a working prototype is a product issue, not just a developer convenience. It affects how many tries we get. If a framework usually generates the right starting point, or if mistakes are easy to spot and fix, that saves time. Add in React’s strong TypeScript support and huge library ecosystem, and React wins for reasons that aren’t about personal preference.

So, the criterion was clear, defensible, and applied. But when I used it for the marketing site, it gave me the wrong answer.

The same criterion, two answers

The site was already using Astro with React islands, but I still considered the decision open. With just ten pages and a rebuild around a new CMS and host coming up, this was the last chance to change the foundation without extra cost. It’s important to use these points of no return thoughtfully.

Two options were genuinely on the table, and both lost.

Vue with Nuxt was my sentimental favorite and the ecosystem I know best. But it lost out because of architecture, not preference. The marketing site has ten pages, but only two parts need client-side state. Nuxt treats the site as a full framework app that renders pages, while Astro treats it as a set of documents that sometimes include a component. That fits this site better. With Nuxt, hydration is handled at the framework level, so every page gets a client-side runtime by default, even for static content. In contrast, Astro allows you to control hydration at the component level, so only the components that actually need interactivity load any runtime code. This not only reduces JavaScript shipped to the browser, but also keeps non-interactive pages fast and light. Using Nuxt would mean loading a framework runtime on every page just for a menu and a form, which felt wasteful. There was another important reason: Astro is framework-agnostic, so sticking with it lets the app team’s React skills carry over to the site. Nuxt would have broken that connection.

Astro with React, which was already in use, is the option most people would choose, and it’s what the earlier criterion suggests. It uses the same monorepo, the same patterns, and the framework that works best with our models. All the arguments for React in our products apply here too.

But that’s not the right answer, because the criterion solves a problem this site doesn’t have. Model fluency helps when you’re writing and rewriting code often. Here, the two interactive components would be written once and rarely touched again, so speed wasn’t important. What was really important was keeping the runtime short, since visitors are likely strangers on their phones, deciding whether to stay on the site.

A broad and open-minded experience helps you ask the right questions, challenge the assumptions that models might make, and recognize when to push for deeper insight.

My next instinct was vanilla

Here’s the part I’d rather leave out.

My first instinct wasn’t to use a more lightweight alternative to React. My instinct was to skip frameworks entirely. With ten static pages, a menu toggle, and a form, I could just write the DOM code by hand and avoid shipping extra code.

That instinct was right for four out of six cases, and it’s how most of the site works. The navbar’s scroll-hide, the founder list, the video feature, and the main button are all custom elements with inline scripts. There’s no framework, no hydration, and no extra code. If something just needs behavior but not real state, a framework is too much for the job.

But that approach didn’t work for the other two cases, and here’s why. The contact form needed more than simple checks, it required clear error messages for each field, accessible notifications for users, a way to prevent duplicate submissions, and logic to distinguish different failure types. Building all of this from scratch isn’t just time-consuming; it can also introduce hard-to-find accessibility issues. By using react-hook-form with a valibot schema, these details are handled automatically, making the form reliable and user-friendly with only a small increase in code.

So the real choice wasn’t framework versus vanilla JavaScript. It was between writing and maintaining my own state machine forever, with zero extra bytes, or using a library-maintained one and accepting some runtime cost.

The solution was Preact! It made the second option lightweight enough that it was an easy decision, and I discovered that by researching, not from prior experience.

AI-amplified work isn’t just about telling an AI to do something, it’s about leveraging it thoughtfully, using it for research, ideation, and brainstorming. Used in the right way, AI should challenge your own assumptions or biases, prompting new lines of thinking you might have overlooked. A broad and open-minded experience helps you ask the right questions, challenge the assumptions that models might make, and recognize when to push for deeper insight. My experience helped me identify the real decision point quickly: a full framework is too much for just one interactive part. But experience didn’t give me the answer, research did. The key is asking the right question, since a working React island technically meets all the written requirements.

What the Metrics Reveal About Framework Decisions

Two separate wins, two days apart, and they're worth keeping apart because they prove different things.

The framework swap, with hydration held constant, on every page and at every width:

  • A page without the form: 68.3 KB gzip and 59.4 KB brotli, down to 20.4 KB and 18.3 KB. A saving of 47.9 KB gzip, or 70.1 percent.

  • The contact page: 81.3 KB and 71.2 KB, down to 33.3 KB and 30.1 KB. A saving of 48.0 KB gzip, or 59.0 percent.

Almost the same number of bytes in both rows, because the entire difference is framework chunks and nothing else.

Which the next measurement makes concrete. The application code, including both components react-hook-form and valibot, went from 12.93 KB (gzip) to 12.92 KB. Thirteen bytes. It compiles to the same weight either way. Nothing was ported; nothing was rewritten. Both components still import from "react". The whole win is runtime, delivered by a config flag and an overrides block.

The hydration change, framework-independent, desktop only:

  • A page without the form, at 1024 pixels and above: 20.4 KB gzip down to zero framework chunks.

  • The contact page: 33.3 KB down to 32.4 KB, which is just the menu component's 944 bytes.

The difference between those two results is the key lesson. A shared runtime only goes away when no part of the page needs it. Since the form hydrates at every width, the contact page always includes the runtime, and only the menu's bytes decrease. One page pays for the runtime, while the other ten stop paying for it above 1024 pixels. They still include inline scripts, so it's zero framework chunks, not zero JavaScript.

One number in there deserves its own paragraph, because it's the one I'd have got wrong without building it:

Preact is often said to be about 3 KB gzipped, and every comparison article mentions that. But when I measured the runtime with compat and Astro’s island runtime, it was closer to 20 KB, almost seven times more. (Preact: 3 kB React-compatible UI library with virtual DOM and hooks., 2026) That’s not anyone’s fault; it’s just the cost of running react-hook-form without changes, and I’d still pay it for a 70 percent saving. The 3 KB number is what you see in documentation, but 20 KB is what I saw in my build.

The learning

Looking back, the biggest shift for me was realizing that with AI-amplified development, deep knowledge of a specific framework is no longer a limiting factor. Instead of defaulting to my most familiar tools, I can now approach each project on its own terms, choosing frameworks and patterns that best fit the problem, not just my own habits. The crucial skill is knowing how to interact with AI: asking the right questions, challenging its assumptions (and my own), and digging for deeper solutions. If I had just asked an AI to “build me a website with React,” it would have delivered, but I’d have ended up with a slow site, poor Core Web Vitals, and weaker SEO. The big learning is that experience now means knowing how to guide AI, not just how to code. That’s what lets me move past old boundaries and build stuff that is genuinely better.

References

Xu, K., Mao, Y., Guan, X. & Feng, Z. (2025). Web-Bench: A LLM Code Benchmark Based on Web Standards and Frameworks. arXiv preprint 2505.07473. https://doi.org/10.48550/arXiv.2505.07473

Pati, S. & Zaki, Y. (2025). Evaluating the Efficacy of Next.js: A Comparative Analysis with React.js on Performance, SEO, and Global Network Equity. arXiv preprint arXiv:2502.15707. https://doi.org/10.48550/arXiv.2502.15707

(July 6, 2025). Most used web frameworks among developers 2025. Statista. https://www.statista.com/statistics/1124699/worldwide-developer-survey-most-used-frameworks-web/

Putra, F. P., Hasbullah, Muslim, F. & Paradina, R. (2025). Technical Performance Comparison of Modern Frontend Frameworks Study on Svelte, React, and Vue. Brilliance Research of Artificial Intelligence 5(1), pp. 355-364. https://doi.org/10.47709/brilliance.v5i1.6133

(2026). Preact: 3 kB React-compatible UI library with virtual DOM and hooks.. Zaira Labs. https://zairalabs.ai/guide/tools/preact/

ShareLinkedIn