Astro
Upgrade to Astro v3
Upgrade to Astro v3
This guide will help you migrate from Astro v2 to Astro v3.
Need to upgrade an older project to v2? See our older migration guide.
Upgrade Astro
Update your project's version of Astro to the latest version using your package manager. If you're using Astro integrations, please also update those to the latest version.
Example: upgrade React and Tailwind integrations
npm install @astrojs/react@latest @astrojs/tailwind@latest
</Fragment>
<Fragment slot="pnpm">
```shell
# Upgrade to Astro v3.x
pnpm add astro@latest
# Example: upgrade React and Tailwind integrations
pnpm add @astrojs/react@latest @astrojs/tailwind@latest
Example: upgrade React and Tailwind integrations
yarn add @astrojs/react@latest @astrojs/tailwind@latest
</Fragment>
</PackageManagerTabs>
:::note[Need to continue?]
After upgrading Astro to the latest version, you may not need to make any changes to your project at all!
But, if you notice errors or unexpected behavior, please check below for what has changed that might need updating in your project.
:::
## Astro v3.0 Experimental Flags Removed
Remove the following experimental flags from `astro.config.mjs`:
```js del={5-8}
// astro.config.mjs
Removed: pre-0.14 Shiki theme names
In Astro v2.x, some Shiki theme names had been renamed, but the original names were kept for backwards compatibility.
Astro v3.0 removes the original names in favor of the renamed theme names.
What should I do?
If your project uses any of the themes below, rename them to their updated name:
material-darker->material-theme-darkermaterial-default->material-themematerial-lighter->material-theme-lightermaterial-ocean->material-theme-oceanmaterial-palenight->material-theme-palenight
Removed: class:list features
In Astro v2.x, the class:list directive used a custom implementation inspired by clsx with a few extra features like deduplication and Set support.
Astro v3.0 now uses clsx directly for class:list, which does not support deduplication or Set values.
What should I do?
Replace any Set elements passed to the class:list directive with a plain Array.
<Component class:list={[
'a',
'b',
new Set(['c', 'd'])
['c', 'd']
]} />
Removed: passing class:list as a prop
In Astro v2.x, class:list values were sent to components via Astro.props['class:list'].
Astro v3.0 normalizes class:list values into a string before being sent to components via Astro.props['class']
What should I do?
Remove any code that expects to receive the class:list prop.
---
const { class: className, 'class:list': classList } = Astro.props;
const { class: className } = Astro.props;
---
<div
class:list={[className, classList]}
class:list={[className]}
/>
Removed: kebab-case transform for camelCase CSS variables
In Astro v2.x, camelCase CSS variables passed to the style attribute were rendered as both camelCase (as written) and kebab-case (kept for backwards compatibility).
Astro v3.0 removes the kebab-case transform for these camelCase CSS variable names, and only the original camelCase CSS variable is rendered.
---
// src/components/MyAstroComponent.astro
const myValue = "red"
---
<!-- input -->
<div style={{ "--myValue": myValue }}></div>
<!-- output (Astro 2.x) -->
<div style="--my-value:var(--myValue);--myValue:red"></div>
<!-- output (Astro 3.0) -->
<div style="--myValue:red"></div>
What should I do?
If you were relying on Astro to transform kebab-case in your styles, update your existing styles to camelCase to prevent missing styles. For example:
<style>
div {
color: var(--my-value);
color: var(--myValue);
}
</style>
Removed: automatic flattening of getStaticPaths()'s return value
In Astro v2.x, the return value of getStaticPaths() was automatically flattened to allow you to return an array of arrays without errors.
Astro v3.0 removes automatic flattening of getStaticPaths()'s result.
What should I do?
If you're returning an array of arrays instead of an array of objects (as is expected), .flatMap and .flat should now be used to ensure that you are returning a flat array.
An error message indicating that getStaticPath()'s return value must be an array of objects will be provided if you need to update your code.
Moved: astro check now requires an external package
In Astro v2.x, astro check was included in Astro by default, and its dependencies were bundled in Astro. This meant a larger package whether or not you ever used astro check. This also prevented you from having control over the version of TypeScript and the Astro Language Server to use.
Astro v3.0 moves the astro check command out of Astro core and now requires an external package @astrojs/check. Additionally, you must install typescript in your project to use the astro check command.
What should I do?
Run the astro check command after upgrading to Astro v3.0 and follow the prompts to install the required dependencies, or manually install @astrojs/check and typescript into your project.
Deprecated: build.excludeMiddleware and build.split
In Astro v2.x, build.excludeMiddleware and build.split were used to change how specific files were emitted when using an adapter in SSR mode.
Astro v3.0 replaces these build config options with new SSR adapter configuration options to perform the same tasks: edgeMiddleware and functionPerRoute.
What should I do?
Update the Astro config file to now use the new options in the adapter configuration directly.
Deprecated: markdown.drafts
In Astro v2.x, the markdown.drafts configuration allowed you to have draft pages that were available in when running the dev server, but not built in production.
Astro v3.0 deprecates this feature in favor of the content collections method of handling draft pages by filtering manually instead, which gives more control over the feature.
What should I do?
To continue to mark some pages in your project as drafts, migrate to content collections and manually filter out pages with the draft: true frontmatter property instead.
Deprecated: returning simple object in endpoints
In Astro v2.x, endpoints could return a simple object, which would be converted to a JSON response.
Astro v3.0 deprecates this behavior in favor of returning a Response object directly.
What should I do?
Update your endpoints to return a Response object directly.
return new Response(JSON.stringify({ "title": "Bob's blog" }));
}
If you really need to keep the previous format, you can use the ResponseWithEncoding object but will be deprecated in the future.
return new ResponseWithEncoding({ body: { "title": "Bob's blog" }});
}
Changed default: verbatimModuleSyntax in tsconfig.json presets
In Astro v2.x, the verbatimModuleSyntax setting was off by default, with its TypeScript 4.x equivalent importsNotUsedAsValues being enabled in the strict preset.
In Astro v3.0, verbatimModuleSyntax is enabled in every preset.
What should I do?
This option requires that types are imported using the import type syntax.
---
---
While we recommend keeping it on and properly making your type imports with type (as shown above), you can disable it by setting verbatimModuleSyntax: false in your tsconfig.json file if it causes any issues.
{
"compilerOptions": {
"verbatimModuleSyntax": false
}
}
Changed default: port 3000
In Astro v2.x, Astro ran on port 3000 by default.
Astro v3.0 changes the default port to 4321. 🚀
What should I do?
Update any existing references to localhost:3000, for example in tests or in your README, to reflect the new port localhost:4321.
Changed default: import.meta.env.BASE_URL trailingSlash
In Astro v2.x, import.meta.env.BASE_URL appended your base setting with a trailingSlash by default. trailingSlash: "ignore" also appended a trailing slash.
Astro v3.0 no longer appends import.meta.env.BASE_URL with a trailing slash by default, nor when trailingSlash: "ignore" is set. (The existing behavior of base in combination with trailingSlash: "always" or trailingSlash: "never" is unchanged.)
What should I do?
If your base already has a trailing slash, no change is needed.
If your base does not have a trailing slash, add one if you wish to preserve the previous default (or trailingSlash: "ignore") behavior:
Changed default: compressHTML
In Astro v2.x, Astro only compressed your emitted HTML when compressHTML was explicitly set to true. The default value was false.
Astro v3.0 now compresses emitted HTML by default.
What should I do?
You can now remove compressHTML: true from your configuration as this is the new default behavior.
}
Changed: Multiple JSX framework configuration
In Astro v2.x, you could use multiple JSX framework integrations (React, Solid, Preact) in the same project without needing to identify which files belonged to which framework.
Astro v3.0 now requires you to specify which framework to use for your files with new include and exclude integration config options when you have multiple JSX framework integrations installed. This allows Astro to better support single-framework usage, as well as advanced features like React Fast Refresh.
What should I do?
If you are using multiple JSX frameworks in the same project, set include (and optionally exclude) to an array of files and/or folders. Wildcards may be used to include multiple file paths.
We recommend placing common framework components in the same folder (e.g. /components/react/ and /components/solid/) to make specifying your includes easier, but this is not required:
Changed: Astro.cookies.get(key) can return undefined
In Astro v2.x, Astro.cookies.get(key) would always return an AstroCookie object, even if the cookie did not exist. To check for its existence, you needed to use Astro.cookies.has(key).
Astro v3.0 returns undefined for Astro.cookies.get(key) if the cookie does not exist.
What should I do?
This change will not break any code that checks for the existence of the Astro.cookie object before using Astro.cookies.get(key), but is now no longer required.
You can safely remove any code that uses has() to check if the value of Astro.cookies is undefined:
if (Astro.cookies.has(id)) {
const id = Astro.cookies.get(id)!;
}
const id = Astro.cookies.get(id);
if (id) {
}
Changed: running the Astro CLI programmatically
In Astro v2.x, the "astro" package entrypoint exported and ran the Astro CLI directly. It is not recommended to run Astro this way in practice.
Astro v3.0 removes the CLI from the entrypoint, and exports a new set of experimental JavaScript APIs, including dev(), build(), preview(), and sync().
What should I do?
To run the Astro CLI programmatically, use the new experimental JavaScript APIs:
// Start the Astro dev server
const devServer = await dev();
await devServer.stop();
// Build your Astro project
await build();
Changed: internal Astro API entry point export paths
In Astro v2.x, you could import internal Astro APIs from astro/internal/* and astro/runtime/server/*.
Astro v3.0 removes the two entry points in favor of the existing astro/runtime/* entrypoint. Additionally, a new astro/compiler-runtime export has been added for compiler-specific runtime code.
What should I do?
These are entry points for Astro's internal API and should not affect your project. But if you do use these entrypoints, update as shown below:
const result = await transform(source, {
internalURL: 'astro/runtime/server/index.js',
internalURL: 'astro/compiler-runtime',
// ...
});
Feature Upgrades
Upgrade images to v3
astro:assets is no longer behind an experimental flag in Astro v3.0.
<Image /> is now a built-in component and the previous @astrojs/image integration has been removed.
These and other accompanying changes to using images in Astro may cause some breaking changes when you upgrade your Astro project from an earlier version.
Please follow the instructions below as appropriate to upgrade an Astro v2.x project to v3.0.
Upgrade from experimental.assets
If you had previously enabled the experimental flag for astro:assets, you will need to update your project for Astro v3.0 which now includes assets features by default.
Remove experimental.assets flag
Remove the experimental flag:
If necessary, also update your src/env.d.ts file to replace the astro/client-image reference with astro/client:
/// <reference types="astro/client-image" />
/// <reference types="astro/client" />
Remove the ~/assets import alias
This import alias is no longer included by default with astro:assets. If you were using this alias with experimental assets, you must convert them to relative file paths, or create your own import aliases.
---
---
Add simple asset support for Cloudflare, Deno, Vercel Edge and Netlify Edge
Astro v3.0 allows astro:assets to work without errors in Cloudflare, Deno, Vercel Edge and Netlify Edge, which do not support Astro's built-in Squoosh and Sharp image optimization. Note that Astro does not perform any image transformation and processing in these environments. However, you can still enjoy the other benefits of using astro:assets, including no Cumulative Layout Shift (CLS), the enforced alt attribute, and a consistent authoring experience.
If you previously avoided using astro:assets because of these constraints, you can now use them without issues. You can configure the no-op image service to explicitly opt-in to this behavior:
Decide where to store your images
See the Images guide to help you decide where to store your images. You may wish to take advantage of new options for storing your images with the added flexibility astro:assets brings. For example, relative images from your project src/ can now be referenced in Markdown, MDX, and Markdoc using standard Markdown  syntax.
Update existing <img> tags
Previously, importing an image would return a simple string with the path of the image. Now, imported image assets match the following signature:
interface ImageMetadata {
src: string;
width: number;
height: number;
format: string;
}
You must update the src attribute of any existing <img> tags (including any images in UI framework components) and you may also update other attributes that are now available to you from the imported image.
---
---
<img src={rocket} width="250" height="250" alt="A rocketship in space." />
<img src={rocket.src} width={rocket.width} height={rocket.height} alt="A rocketship in space." />
Update your Markdown, MDX, and Markdoc files
Relative images from your project src/ can now be referenced in Markdown, MDX, and Markdoc using standard Markdown  syntax.
This allows you to move your images from the public/ directory to your project src/ where they will now be processed and optimized. Your existing images in public/ and remote images are still valid but are not optimized by Astro's build process.
# My Markdown Page
<!-- Local images now possible! -->

<!-- Keep your images next to your content! -->

If you require more control over your image attributes, we recommend using the .mdx file format, which allows you to include Astro's <Image /> component or a JSX <img /> tag in addition to the Markdown syntax. Use the MDX integration to add support for MDX to Astro.
Remove @astrojs/image
If you were using the image integration in Astro v2.x, complete the following steps:
You must [remove the integration](/en/guides/integrations/#removing-an-integration) by uninstalling and then removing it from your `astro.config.mjs` file.
```js del={3,7}
// astro.config.mjs
import { defineConfig } from 'astro/config';
import image from '@astrojs/image';
export default defineConfig({
integrations: [
image(),
]
})
```
Update types (if required).
If you had special types configured for `@astrojs/image` in `src/env.d.ts`, you may need to change them back to the default Astro types if your upgrade to v3 did not complete this step for you. ```ts title="src/env.d.ts" del={1} ins={2} /// <reference types="@astrojs/image/client" /> /// <reference types="astro/client" /> ``` Similarly, update `tsconfig.json` if necessary: ```json title="tsconfig.json" del={3} ins={4} { "compilerOptions": { "types": ["@astrojs/image/client"] "types": ["astro/client"] } } ```Migrate any existing
<Image />components.Change all
importstatements from@astrojs/image/componentstoastro:assetsin order to use the new built-in<Image />component.Remove any component attributes that are not currently supported image asset properties.
For example,
aspectRatiois no longer supported, as it is now automatically inferred from thewidthandheightattributes.--- import { Image } from '@astrojs/image/components'; import { Image } from 'astro:assets'; import localImage from '../assets/logo.png'; const localAlt = 'The Astro Logo'; --- <Image src={localImage} width={300} aspectRatio="16:9" alt={localAlt} />Choose a default image service.
Sharp is now the default image service used for
astro:assets. If you would like to use Sharp, no configuration is required.If you would prefer to use Squoosh to transform your images, update your config with the following
image.serviceoption:import { defineConfig, squooshImageService } from 'astro/config'; export default defineConfig({ image: { service: squooshImageService(), }, });
Update Content Collections schemas
You can now declare an associated image for a content collections entry, such as a blog post's cover image, in your frontmatter using its path relative to the current folder.
The new image helper for content collections lets you validate the image metadata using Zod. Learn more about how to use images in content collections
Navigating Image Imports in Astro v3.0
In Astro v3.0, if you have to preserve the old import behavior for images and require a string representation of the image's URL, append ?url to the end of your image path when importing it. For example:
---
---
<svg>
<use xlink:href={Sprite + '#cart'} />
</svg>
This approach ensures you obtain the URL string. Keep in mind that during development, Astro uses a src/ path, but upon building, it generates hashed paths like /_astro/cat.a6737dd3.png.
If you prefer to work directly with the image object itself, you can access the .src property. This approach is best for tasks like managing image dimensions for Core Web Vitals metrics and preventing CLS.
If you are transitioning into the new import behavior, combining ?url and .src methods might be the right method for seamless image handling.
Upgrade view transitions to v3
View transitions are no longer behind an experimental flag in Astro v3.0.
If you had not enabled this experimental flag in Astro 2.x, this will not cause any breaking changes to your project. The new View Transitions API has no effect on your existing code.
If you were previously using experimental view transitions, there may be some breaking changes when you upgrade your Astro project from an earlier version.
Please follow the instructions below as appropriate to upgrade an Astro v2.x project configured with experimental.viewTransitions: true to v3.0.
Upgrade from experimental.viewTransitions
If you had previously enabled the experimental flag for view transitions, you will need to update your project for Astro v3.0 which now allows view transitions by default.
Remove experimental.viewTransitions flag
Remove the experimental flag:
Update import source
The <ViewTransitions /> component has been moved from astro:components to astro:transitions. Update the import source across all occurrences in your project.
---
</script>
The event astro:beforeload has been renamed to astro:after-swap. Rename all occurrences in your project.
<script>
document.addEventListener('astro:beforeload astro:after-swap', setDarkMode);
</script>
Community Resources
Know a good resource for Astro v3.0? Edit this page and add a link below!
Known Issues
There are currently no known issues.