# Migrating from Other Web Frameworks to Astro: A Complete Technical Guide

> Learn to migrate from React Vue Svelte or Solid to Astro effortlessly. This guide covers scaffolding routing data fetching and API conversion for a smooth transition. Get started today.

- Repository: [Astro/astro](https://github.com/withastro/astro)
- Tags: migration-guide
- Published: 2026-03-06

---

**Migrating from React, Vue, Svelte, or Solid to Astro involves scaffolding a new project with your existing UI framework integration, converting routes to Astro's file-based system in `src/pages/`, moving data fetching into server-side `load` functions or Content Collections, and replacing deprecated APIs like `Astro.resolve` with `import.meta.glob`.**

When migrating from other web frameworks to Astro, you are fundamentally shifting from a client-side hydration model to Astro's "islands architecture" that renders HTML on the server by default. This guide walks through the concrete steps required to migrate projects from React, Vue, Svelte, Solid, or similar frameworks into Astro, referencing specific implementation details from the `withastro/astro` source code.

## Scaffold the Project and Configure UI Framework Integration

Start by creating a fresh Astro project using the official CLI:

```bash
npm create astro@latest

```

The default configuration created by the CLI is documented in [`packages/astro/README.md`](https://github.com/withastro/astro/blob/main/packages/astro/README.md) and [`packages/astro/src/cli/docs/core/open-docs.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/cli/docs/core/open-docs.ts). After scaffolding, add the integration for whichever UI framework you are migrating from:

| Framework | Integration Package | Install Command |
|-----------|---------------------|-----------------|
| React | `@astrojs/react` | `npm install @astrojs/react` |
| Vue | `@astrojs/vue` | `npm install @astrojs/vue` |
| Svelte | `@astrojs/svelte` | `npm install @astrojs/svelte` |
| Solid | `@astrojs/solid` | `npm install @astrojs/solid` |

Each integration's specific configuration options are documented in their respective README files under `packages/integrations/`.

## Convert Routes to File-Based Routing

Astro uses a file-based routing system where every file in `src/pages/` becomes a route. This replaces framework-specific routers like React Router or Vue Router.

For example, converting a React route [`/src/pages/home.jsx`](https://github.com/withastro/astro/blob/main//src/pages/home.jsx) to Astro:

```astro
---
// src/pages/home.astro
import Home from "../components/Home.jsx";
---
<Home />

```

The underlying Vite plugin that processes these routes is documented in [`packages/astro/src/vite-plugin-html/README.md`](https://github.com/withastro/astro/blob/main/packages/astro/src/vite-plugin-html/README.md). If your previous framework used nested layouts, create an `src/layouts/` directory and reference layouts via frontmatter:

```astro
---
// src/pages/blog/[slug].astro
import BlogLayout from "../layouts/BlogLayout.astro";
export const layout = BlogLayout;
---
<slot />

```

## Adapt Component Import Models

Astro treats UI components as **partial islands** that can be imported directly into `.astro` files. Replace framework-specific entry points with Astro's component-oriented imports:

```astro
---
// src/components/Button.astro
import { Button as ReactButton } from "../ui/react/Button.jsx";
---
<ReactButton class="primary">Click me</ReactButton>

```

For Vue migrations, import `.vue` files directly:

```astro
---
// src/components/Chart.astro
import Chart from "./Chart.vue";
---
<Chart :data={data} />

```

The Vue integration's import handling is defined in [`packages/integrations/vue/README.md`](https://github.com/withastro/astro/blob/main/packages/integrations/vue/README.md).

## Migrate Data Fetching to Server-Side Logic

Move data-fetching logic from client-side `useEffect` hooks or component lifecycles into Astro's server-side `load` functions:

```astro
---
// src/pages/posts/[slug].astro
export async function load({ params }) {
  const post = await fetch(`https://my.api/posts/${params.slug}`).then(r => r.json());
  return { post };
}
---
<h1>{post.title}</h1>
<p>{post.content}</p>

```

For static content, use the **Content Collections** API introduced in v4:

```ts
// src/content/config.ts
import { defineCollection } from "astro:content";

export const collections = {
  blog: defineCollection({ type: "content" })
};

```

The migration to `import.meta.glob` is discussed in [`packages/astro/CHANGELOG-v4.md`](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG-v4.md) at line 5341, which states: "The easiest path is to migrate to `import.meta.glob`". If you previously used `Astro.resolve`, replace it with `import.meta.glob` or the Content Collections API.

## Configure Static vs. Server Rendering

In `astro.config.mjs`, specify the default rendering mode:

```js
export default {
  output: "static", // default – prerender all pages
  // output: "server", // for SSR pages
};

```

Individual pages can override the global setting:

```astro
---
export const prerender = false;
---

```

The `output` flag behavior is documented in [`packages/astro/CHANGELOG-v4.md`](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG-v4.md) at line 737.

## Select and Configure Deployment Adapters

Astro's adapters replace framework-specific deployment pipelines. For example, migrating from a custom Netlify function:

```bash
pnpm add -D @astrojs/netlify

```

```js
// astro.config.mjs
import netlify from "@astrojs/netlify";

export default {
  adapter: netlify(),
};

```

For Cloudflare Pages migrations, use the Cloudflare Workers adapter. Migration notes live in [`packages/integrations/cloudflare/CHANGELOG.md`](https://github.com/withastro/astro/blob/main/packages/integrations/cloudflare/CHANGELOG.md) at line 112.

## Replace Deprecated APIs

| Removed API | New Replacement | Source Reference |
|-------------|----------------|------------------|
| `Astro.resolve` | `import.meta.glob` or Content Collections | [`packages/astro/CHANGELOG-v2.md`](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG-v2.md) line 2019 |
| `Astro.locals.runtime` | `ctx.locals` in API routes or adapters | [`packages/integrations/cloudflare/CHANGELOG.md`](https://github.com/withastro/astro/blob/main/packages/integrations/cloudflare/CHANGELOG.md) line 15075 |
| Pre-Shiki theme names (v0.14) | New theme names | [`packages/markdown/remark/CHANGELOG.md`](https://github.com/withastro/astro/blob/main/packages/markdown/remark/CHANGELOG.md) lines 709-728 |

## End-to-End Migration Example

Below is a complete conversion of a React page that fetched data, used a component, and was statically rendered.

**Original React ([`src/pages/User.jsx`](https://github.com/withastro/astro/blob/main/src/pages/User.jsx))**

```jsx
import React from "react";
import Avatar from "../components/Avatar";

export default function User({ id }) {
  const [user, setUser] = React.useState(null);
  React.useEffect(() => {
    fetch(`/api/users/${id}`).then(r => r.json()).then(setUser);
  }, [id]);

  return user ? (
    <div>
      <Avatar src={user.avatar} />
      <h2>{user.name}</h2>
    </div>
  ) : <p>Loading…</p>;
}

```

**Converted Astro (`src/pages/user/[id].astro`)**

```astro
---
// src/pages/user/[id].astro
import Avatar from "../../components/Avatar.jsx";

export async function load({ params }) {
  const user = await fetch(`https://my.api/users/${params.id}`).then(r => r.json());
  return { user };
}
---
{user ? (
  <div>
    <Avatar src={user.avatar} />
    <h2>{user.name}</h2>
  </div>
) : <p>Loading…</p>}

```

Key changes:
- Data fetching moved to a `load` function that runs once at build or request time
- The React component is imported and used directly without `useEffect` because data is already present

## Summary

- **Scaffold with framework integrations**: Use `npm create astro@latest` then add `@astrojs/react`, `@astrojs/vue`, or other integrations to reuse your existing components.
- **Adopt file-based routing**: Move all routes to `src/pages/` and convert dynamic routes using `[param].astro` syntax.
- **Shift data fetching server-side**: Replace client-side `useEffect` data fetching with Astro's `load` functions or the Content Collections API.
- **Configure rendering modes**: Set `output: "static"` or `output: "server"` in `astro.config.mjs` and use `export const prerender` for page-level overrides.
- **Update deployment adapters**: Replace framework-specific deployment logic with official adapters like `@astrojs/netlify` or `@astrojs/cloudflare`.
- **Remove deprecated APIs**: Replace `Astro.resolve` with `import.meta.glob`, update `Astro.locals.runtime` to `ctx.locals`, and verify Shiki theme names.

## Frequently Asked Questions

### How do I migrate client-side data fetching to Astro?

Move your data fetching logic from React's `useEffect` or Vue's `onMounted` into Astro's server-side `load` function. This function runs before the component renders, allowing you to fetch data from APIs or databases and pass it as props to your components. For static sites, this happens at build time; for SSR sites, it runs on each request.

### Can I keep using my existing React or Vue components during migration?

Yes. Astro's "Bring your own UI framework" philosophy allows you to import React, Vue, Svelte, or Solid components directly into `.astro` files. Install the appropriate integration (e.g., `@astrojs/react`), import your component, and Astro will render it as an interactive island only when needed, while keeping the surrounding page as static HTML.

### What replaces `Astro.resolve` when migrating from older Astro versions?

Replace `Astro.resolve` with `import.meta.glob` or migrate to the Content Collections API introduced in Astro v4. According to [`packages/astro/CHANGELOG-v4.md`](https://github.com/withastro/astro/blob/main/packages/astro/CHANGELOG-v4.md), `import.meta.glob` is the recommended path for dynamically importing files, while Content Collections provide type-safe content management for blogs, documentation, and marketing sites.

### How do I choose between static and server output during migration?

Set the default rendering mode in `astro.config.mjs` using `output: "static"` (default, prerendered at build time) or `output: "server"` (SSR on each request). Individual pages can override this default by exporting `prerender = false` for server-rendered pages within a static site, or `prerender = true` for static pages within a server site. Choose based on whether your content changes frequently (use server) or can be built ahead of time (use static).