FORGE
Services About Blog
Astro in production: six months on
Engineering 5 February 2026 · 9 min read

Astro in production: six months on

We moved our client projects from Next.js to Astro in late 2025. Here is an honest account of what improved, what got harder, and what we would do differently.

RO
Robert Okoroafor
FORGE

We moved our client projects from Next.js to Astro in Q3 2025. The decision was not dramatic — Astro had reached the point where it was the obvious choice for the majority of what we build: content-heavy marketing sites and agency portfolios. The performance model made sense. The islands architecture made sense. The zero-JS-by-default made sense.

Six months later, here is an honest account of what is better, what is harder, and what we would do differently.

What got measurably better

Performance, immediately. The first Astro project we shipped scored 100 across all Lighthouse categories on the first audit. Not because we worked for it — because the framework's defaults made it difficult to ship badly. No client-side JavaScript unless explicitly added. Images optimised at build time. Fonts handled correctly out of the box.

The Next.js projects we had shipped the previous year required performance work after the fact: auditing what JavaScript was loading and why, optimising images that the build had not caught, reworking hydration strategies for components that did not need to be interactive. With Astro, most of that work simply did not exist.

Content management integration. The Sanity integration in Astro is as close to seamless as anything we have used. The content fetches in the frontmatter, the data arrives typed, the component renders it. No API routes, no server functions, no client-side fetching unless the use case genuinely requires it. The mental model is simple enough that the person writing the content schema and the person writing the component are clearly operating on the same abstraction.

Developer experience for components. Astro components are HTML with a script fence at the top. There is no framework to learn, no lifecycle to manage, no state system to navigate for components that do not have state. The cognitive load of building a marketing page dropped substantially.

What got harder

React components with complex state. We had built a filter interface — faceted search, client-side — in React. Bringing it into an Astro project required wrapping it in an island with client:load. That works. But the boundary between the Astro component and the React island is a seam. Props cross it one way. Events cross it the other way with effort. State that wants to be shared across multiple islands requires a store — we used nanostores, which is fine, but it is an additional dependency and an additional mental model.

For sites with significant interactivity, Astro's component model adds friction relative to a full React application. That is an appropriate trade-off for most of what we build. It is not the right trade-off for everything.

Routing edge cases. Astro's file-based routing is clear and predictable for the common case. Dynamic routes with complex patterns required more careful thought than the equivalent in Next.js. The interaction between dynamic routes and API endpoints, and between static and server-rendered pages in the same project, took longer to get right than expected.

The ecosystem is smaller. Not thin — the core is solid and the community is active. But the number of Astro-specific libraries and solutions to common problems is smaller than the React/Next.js ecosystem. For problems that would have a well-maintained package in the React world, the Astro world sometimes requires building from scratch or reaching for a React dependency and wrapping it in an island.

What we would do differently

We would be more deliberate about the island boundaries from the start. On one project, we added interactivity incrementally — a filter here, a form there — and the islands accumulated without a clear architecture. The result was not broken, but it was harder to maintain than a project where we had thought through the interactive surface area before writing the first component.

We would also document the client directive decisions. client:load, client:visible, client:idle — the choice between them has performance implications that are easy to set and forget. On a project with multiple contributors, the wrong directive gets used because the right one was not recorded anywhere.

The summary

Astro is the right choice for what we build. The performance baseline is better, the component model is simpler for content sites, and the Sanity integration is clean. The trade-offs — smaller ecosystem, island boundary friction for complex interactivity — are real but manageable.

We would not go back. We would be more deliberate about the decisions that are easy to get subtly wrong.

New project

Start a
project.

Discovery call
Loading calendar…