Platform Migration

Moving a Next.js site to Astro — and deciding what stops being an application

This is not a like-for-like replatform. Next.js is an application builder that can serve documents; Astro is a document builder that can host an application. The shape of the migration follows from how much of your site is which.

The problem

The framework changes what a page is, not only how it is built

A Next.js site is organised around routes that render, fetch and hydrate. An Astro site is organised around documents that may contain islands. Those are different mental models, and the migration is mechanical exactly to the extent that the site was already mostly documents. Where it was not — where a route's behaviour lives in the browser, where state is shared across views, where client-side routing carries the reader between them — the work is not a port. It is a decision about each of those, made route by route.

  • The migration is being scoped as a like-for-like framework change
  • The site's client-side state has never been enumerated
  • Some routes are genuinely interactive and nobody has decided which
  • Client-side routing carries readers between views that could be pages
  • The existing rendering modes were inherited rather than chosen
  • The requirement is less JavaScript shipped, and it stops there
  • The estimate is built from a page count
  • Redirects, canonicals and structured data are assumed to carry over
  • A framework was picked to solve a hosting or build problem, and the migration means more than that
Who this is for

The people who usually bring us this problem

A team with a Next.js site that is mostly content

The framework is being paid for and the site behaves like a document library. This is the migration that fits.

A team whose hosting or build cost is the driver

The problem is real, and it is worth knowing whether the framework change is the thing that solves it.

A team that has been told to migrate

You need to know which parts of this are a port and which are a rebuild, before the estimate is written rather than after.

What it costs

What this costs while it goes unfixed

Engineering faults are rarely confined to the engineering layer. These are the commercial consequences we see most often.

The cost is set by how much of the site is an application, not by how many pages it has

A hundred content routes converted from one framework to another is largely mechanical work. Three routes with shared client state, optimistic updates and a client-side router are a rebuild, and they may be three pages. A page count is the least useful number available for scoping this, and it misleads in both directions — a large static estate is cheaper than it looks, and a small interactive one can be considerably more expensive.

The server and client boundary is drawn somewhere else

Next.js separates what runs on the server from what runs in the browser, and a good deal of the site's structure follows that line. Astro draws a different one: static by default, interactive where declared. The mapping is therefore not a rename. Each interactive component becomes a decision about whether it should be interactive at all, which is a question the previous architecture did not force.

Client-side routing, where it is used, has no direct equivalent

Next.js's router moves between views without a document load. Astro's default is a document load per navigation, and the view-transition and prefetch options soften that without reproducing it. Where the site depends on state persisting across navigations, that is an architectural change rather than a framework swap, and it is the item most often missing from an estimate.

Removing the framework removes what it was quietly doing

Routing conventions, image handling, font loading, metadata management and middleware all stop being provided. Some have direct Astro equivalents and some are work. The migration estimate is largely the list of things nobody remembered the framework was doing, which is why the list is compiled before the estimate rather than during the build.

The search position starts from a better place and is still re-verified

Astro serves complete HTML by default, which is the strongest starting position there is for a crawler, and it is a starting position rather than a promise about your site. Routes change alongside the framework, so redirects, canonicals, structured data and sitemaps are all verified on the new output rather than assumed to have carried over with the content.

What we do about it

Capabilities

Each of these is work we carry out, not an area we advise on.

Route classification before any migration

Every route assessed for how much of it is a document and how much is an application, and where its behaviour would live on Astro. This produces the number the work should be scoped from, and it is a different number from the page count.

Application surface inventory

Client state, client routing, browser-only dependencies, shared providers and anything that reads from `window`. Each one listed with a decision attached: keep as an island, move to build time, or rebuild as a page.

Island design from existing components

Which existing components survive as islands, which become static markup, and what each remaining one needs from the browser. Astro renders React, so the question is not which components can be reused — it is which of them should still ship JavaScript to a reader.

Rendering mode per route class

What is generated at build time, what is rendered on request, and where a hybrid arrangement is needed because most of the estate is static and one part of it is not. Decided against change frequency and required freshness rather than inherited from the previous configuration.

Framework-provided behaviour replaced

Metadata, sitemaps, canonical URLs, image handling, font loading and redirects, each either mapped to an Astro feature or added as work. Everything the framework did implicitly becomes explicit, and the list is compiled before the build.

Redirects, canonicals and sitemaps

A complete inventory of existing addresses, mapped by class to the new routes, with the redirect layer owned by whoever serves the request and the map built from a census of what the site has served rather than from what somebody remembers.

Progressive migration where the site is large

Route classes moved in sequence, with the previous framework still serving everything not yet moved. A migration moved in reviewable steps is one where the search consequence of each step is attributable to that step rather than to a launch.

Verification against the previous site

Delivery and search measured before and after on the same routes, with the difference attributable to a specific change. A platform migration is a large enough change that an unmeasured one cannot be judged, only hoped about.

How we work

Engineering methodology

The sequence is deliberate. The order is usually what determines whether the work holds or has to be repeated.

  1. Classify every route before estimating anything

    Document or application, and how much of it is each. This is the number the estimate should be built from. A page count misleads in both directions, and the classification is also what tells a reader whether this is the right migration for them at all.

  2. Inventory what the framework is doing silently

    Routing conventions, image pipelines, font loading, metadata assembly, middleware. Each is work that is currently invisible because it happens without being asked for, and each becomes visible on the day the framework changes.

  3. Decide per route whether it still needs to be interactive

    Not every component that is interactive needs to be. A static form with a server endpoint, a details element, a link — these and others have replaced whole islands in ordinary sites, and at this point in the work the decision costs nothing to make.

  4. Keep the old site serving what has not moved

    Route classes migrated in sequence and verified one at a time. No release has to be right first time, and each step's search consequence is attributable to that step rather than to a cutover.

  5. Build the redirect map from a census

    Every address the site has ever served, in every pattern it has used, taken before the new routes are designed. It is the cheapest insurance in the project and the loss it prevents is gradual, permanent and easy to attribute to something else.

  6. Measure the delivered response and the search outcome

    The HTML as served, the metadata, the structured data, the canonicals and the redirects as followed, plus search measurements against a pre-migration baseline. Everything the framework change alters is verified rather than assumed to have survived.

Deliverables

What an engagement produces

Documentation is a deliverable, not an afterthought. On most of these engagements a large part of the value is a defect report precise enough for another team to act on.

Decision and scope

  • Which routes are documents, which are applications, and what each application surface becomes
  • The framework behaviours that stop being provided, and who replaces each
  • Migration order by route class
  • Rendering mode per route class
  • Complete URL inventory, across every pattern the site has used

Build

  • Astro routes for the migrated classes
  • Islands built from the components that still need the browser
  • A replacement for each framework-provided behaviour: metadata, images, fonts, sitemaps, redirects
  • Hybrid rendering where part of the estate needs it
  • The previous framework still serving every route not yet migrated

Verify and hand over

  • What each route delivers before JavaScript runs
  • Redirects, canonicals and structured data verified on the response
  • Search measurements against a pre-migration baseline
  • Delivery measurements before and after, on the same routes
  • Where to add a route, a redirect or a rendering rule
Under the hood

Architecture and technology

Route one: the site is mostly documents

  • Content routes converted to Astro templates, largely mechanical work
  • Interactive elements reduced to a small number of islands
  • Build-time rendering for everything that does not change per request
  • A document load per navigation, which the previous site may have avoided
  • Framework-provided behaviour replaced explicitly, one item at a time
  • The smaller of the two migrations, and the one that fits most Next.js content sites

Route two: parts of it are genuinely an application

  • Application surfaces enumerated, each with a decision recorded
  • Shared client state either kept inside a single island or lifted to the server
  • Client-side routing either accepted as document loads or rebuilt deliberately
  • Server rendering where content changes too often to pre-generate
  • The interactive part carrying its cost within a page that is otherwise static
  • A larger project, and usually a smaller one than replacing the application with something else
Adjacent problems

If this is not quite your problem

These overlap at the edges. Sending you to the right page is more useful than having you work it out.

Whether to decouple at all is the open question

Choosing and designing a decoupled stack, which is a different engagement.

Headless website development

The site is staying on Next.js

The application engineering this migration is moving away from.

Next.js development

The destination framework needs building

Islands, typed content and rendering modes on the other side of the move.

Astro site development

Search visibility is the main risk

The general migration discipline, including redirects and indexation recovery.

Website migrations

Traffic has already declined after a move

Establishing what a migration missed before changing anything else.

SEO traffic recovery
Questions

Frequently asked

Is this a like-for-like migration?

No, and treating it as one is the main way it goes wrong. Next.js is an application framework that can render documents; Astro is a document framework that can host applications. A content route converts cleanly. A route whose behaviour lives in the browser — shared state, optimistic updates, client-side routing between views — has no direct equivalent to convert to, and becomes a decision rather than a port. Which of those you have, and how many, is established by classifying the routes before anything is estimated.

Do you have an example of this migration?

Yes, and it is the site you are reading. Our own marketing site was migrated from a Next.js static export to Astro — a hundred and seventeen routes and seventeen legacy redirect rules as of 26 September 2026, with the structured data, canonicals and sitemaps carried over. That is a dated record of what the migration covered rather than a count of the site today, which is larger. What a reader can verify is the artefact rather than the outcome: the served routes, the sitemap, the published redirects and the parity checks in the repository are all inspectable without asking us for anything. What it does not show is work inside somebody else's constraints, because it is our own site, migrated for our own reasons with no external stakeholder — and that is what a client migration actually tests. We would rather say that plainly than let the example carry more than it can, which is why the evidence section on this page is empty and the migration is described as work performed rather than as a result.

Will Astro improve our search visibility?

Astro serves complete HTML by default, which is the strongest starting position available for a crawler, and that is a statement about the framework rather than about your site. Two things decide the actual outcome, and neither is the framework choice. The first is the redirect map, because a migration changes addresses and that is where visibility is usually lost — built from a census of what the site has served rather than from memory. The second is whether metadata, canonicals and structured data are verified on the new output rather than assumed to have carried across with the content. A migration with a complete redirect map and verified output keeps what it had. There are no figures to promise here and we do not promise any.

How long does it take?

We will not give a duration before the routes are classified and the application surfaces are enumerated, because those two things decide the answer and a page count does not. One site of a hundred content routes can be a shorter project than another site of ten routes with shared client state and a router. What we will give after the assessment is the route classification, the migration order, the rendering mode per class and the list of framework behaviour that has to be replaced — which is what a plan can honestly be built from.

Should we migrate at all?

Sometimes no, and the classification is what settles it. A site whose routes are genuinely applications — with shared client state, client-side navigation and interactive views — is not paying for the framework it is using, and a document framework would make rebuilding that behaviour the whole project. In that case staying on Next.js and fixing the parts that are actually slow or stale is the better-shaped work, and it is the answer we would give. Astro fits a site that is mostly content and has been carrying an application runtime to serve it.

Can we keep the Next.js site running while the new one is built?

Yes, and it is how the work is done. Routes migrate in classes, with the previous site still serving everything not yet moved, so there is no period where the site is unavailable and no single release that has to be right first time. The cost is that two rendering paths exist for a period, which is real complexity, and it is usually worth paying against the alternative of a large and irreversible cutover.

Bring us the problem you have not been able to fix

Describe what is happening rather than what you think the cause is. If we are not the right people for it, we will say so.