#11780c6622ad Thanks @Princesseuh! - Deprecates the Squoosh image service, to be removed in Astro 5.0. We recommend migrating to the default Sharp service.
#1179041c3fcb Thanks @sarah11918! - Updates the documentation for experimental astro:env with a corrected link to the RFC proposal
#1177386a3391 Thanks @ematipico! - Changes messages logged when using unsupported, deprecated, or experimental adapter features for clarity
#1174589bab1e Thanks @bluwy! - Prints prerender dynamic value usage warning only if it’s used
#1177149650a4 Thanks @florian-lefebvre! - Fixes an error thrown by astro sync when an astro:env virtual module is imported inside the Content Collections config
#11744b677429 Thanks @bluwy! - Disables the WebSocket server when creating a Vite server for loading config files
#10742b6fbdaa Thanks @ematipico! - The lowest version of Node supported by Astro is now Node v18.17.1 and higher.
#11715d74617c Thanks @Princesseuh! - Refactor the exported types from the astro module. There should normally be no breaking changes, but if you relied on some previously deprecated types, these might now have been fully removed.
In most cases, updating your code to move away from previously deprecated APIs in previous versions of Astro should be enough to fix any issues.
Previously, non-boolean attributes may not have included their values when rendered to HTML. In Astro v5.0, the values are now explicitly rendered as ="true" or ="false"
In the following .astro examples, only allowfullscreen is a boolean attribute:
<!-- src/pages/index.astro --><!-- `allowfullscreen` is a boolean attribute -->
<pallowfullscreen={true}></p>
<pallowfullscreen={false}></p>
<!-- `inherit` is *not* a boolean attribute -->
<pinherit={true}></p>
<pinherit={false}></p>
<!-- `data-*` attributes are not boolean attributes -->
<pdata-light={true}></p>
<pdata-light={false}></p>
Astro v5.0 now preserves the full data attribute with its value when rendering the HTML of non-boolean attributes:
<p allowfullscreen></p>
<p></p>
<p inherit="true"></p>
<p inherit></p>
<p inherit="false"></p>
<p data-light></p>
<p data-light="true"></p>
<p></p>
<p data-light="false"></p>
If you rely on attribute values, for example to locate elements or to conditionally render, update your code to match the new non-boolean attribute values:
This change removes support for the functionPerRoute option both in Astro and @astrojs/vercel.
This option made it so that each route got built as separate entrypoints so that they could be loaded as separate functions. The hope was that by doing this it would decrease the size of each function. However in practice routes use most of the same code, and increases in function size limitations made the potential upsides less important.
Additionally there are downsides to functionPerRoute, such as hitting limits on the number of functions per project. The feature also never worked with some Astro features like i18n domains and request rewriting.
Given this, the feature has been removed from Astro.
🐞 Patch Changes
#1174589bab1e Thanks @bluwy! - Prints prerender dynamic value usage warning only if it’s used
When an HTML minifier strips away the server island comment, the script can’t correctly know where the end of the fallback content is. This makes it so that it simply doesn’t remove any DOM in that scenario. This means the fallback isn’t removed, but it also doesn’t crash the browser.
#11657a23c69d Thanks @bluwy! - Deprecates the option for route-generating files to export a dynamic value for prerender. Only static values are now supported (e.g. export const prerender = true or = false). This allows for better treeshaking and bundling configuration in the future.
Adds a new "astro:route:setup" hook to the Integrations API to allow you to dynamically set options for a route at build or request time through an integration, such as enabling on-demand server rendering.
To migrate from a dynamic export to the new hook, update or remove any dynamic prerender exports from individual routing files:
Use injectTypes() in the astro:config:done hook to inject types into your user’s project by adding a new a *.d.ts file.
The filename property will be used to generate a file at /.astro/integrations/<normalized_integration_name>/<normalized_filename>.d.ts and must end with ".d.ts".
The content property will create the body of the file, and must be valid TypeScript.
Additionally, injectTypes() returns a URL to the normalized path so you can overwrite its content later on, or manipulate it in any way you want.
#11360a79a8b0 Thanks @ascorbic! - Adds support for Intellisense features (e.g. code completion, quick hints) for your content collection entries in compatible editors under the experimental.contentIntellisense flag.
import { defineConfig } from'astro';
exportdefaultdefineConfig({
experimental: {
contentIntellisense: true,
},
});
When enabled, this feature will generate and add JSON schemas to the .astro directory in your project. These files can be used by the Astro language server to provide Intellisense inside content files (.md, .mdx, .mdoc).
Note that at this time, this also require enabling the astro.content-intellisense option in your editor, or passing the contentIntellisense: true initialization parameter to the Astro language server for editors using it directly.
The new Content Layer API builds upon content collections, taking them beyond local files in src/content/ and allowing you to fetch content from anywhere, including remote APIs. These new collections work alongside your existing content collections, and you can migrate them to the new API at your own pace. There are significant improvements to performance with large collections of local files.
Getting started
To try out the new Content Layer API, enable it in your Astro config:
import { defineConfig } from'astro';
exportdefaultdefineConfig({
experimental: {
contentLayer: true,
},
});
You can then create collections in your src/content/config.ts using the Content Layer API.
Loading your content
The core of the new Content Layer API is the loader, a function that fetches content from a source and caches it in a local data store. Astro 4.14 ships with built-in glob() and file() loaders to handle your local Markdown, MDX, Markdoc, and JSON files:
src/content/config.ts
import { defineCollection, z } from'astro:content';
import { glob } from'astro/loaders';
constblog=defineCollection({
// The ID is a slug generated from the path of the file relative to `base`
You’re not restricted to the built-in loaders – we hope you’ll try building your own. You can fetch content from anywhere and return an array of entries:
// Must return an array of entries with an id property,
// or an object with IDs as keys and entries as values
return data.map((country) => ({
id: country.cca3,
...country,
}));
},
// optionally add a schema to validate the data and make it type-safe for users
// schema: z.object...
});
exportconstcollections= { countries };
For more advanced loading logic, you can define an object loader. This allows incremental updates and conditional loading, and gives full access to the data store. It also allows a loader to define its own schema, including generating it dynamically based on the source API. See the the Content Layer API RFC for more details.
Sharing your loaders
Loaders are better when they’re shared. You can create a package that exports a loader and publish it to npm, and then anyone can use it on their site. We’re excited to see what the community comes up with! To get started, take a look at some examples. Here’s how to load content using an RSS/Atom feed loader:
#1167834da907 Thanks @ematipico! - Fixes a case where omitting a semicolon and line ending with carriage return - CRLF - in the prerender option could throw an error.
Server island props are now encrypted with a key generated at build-time. This is intended to prevent accidentally leaking secrets caused by exposing secrets through prop-passing. This is not intended to allow a server island to be trusted to skip authentication, or to protect against any other vulnerabilities other than secret leakage.
#11655dc0a297 Thanks @billy-le! - Fixes Astro Actions input validation when using default values with a form input.
#11689c7bda4c Thanks @ematipico! - Fixes an issue in the Astro actions, where the size of the generated cookie was exceeding the size permitted by the Set-Cookie header.
#1165813b912a Thanks @bholmesdev! - Fixes orThrow() type when calling an Action without an input validator.
#11603f31d466 Thanks @bholmesdev! - Improves user experience when render an Action result from a form POST request:
Removes “Confirm post resubmission?” dialog when refreshing a result.
Removes the ?_astroAction=NAME flag when a result is rendered.
Also improves the DX of directing to a new route on success. Actions will now redirect to the route specified in your action string on success, and redirect back to the previous page on error. This follows the routing convention of established backend frameworks like Laravel.
For example, say you want to redirect to a /success route when actions.signup succeeds. You can add /success to your action string like so:
On error, Astro will redirect back to the current page.
You can retrieve the action result from either page using the Astro.getActionResult() function.
Note on security
This uses a temporary cookie to forward the action result to the next page. The cookie will be deleted when that page is rendered.
⚠ The action result is not encrypted. In general, we recommend returning minimal data from an action handler to a) avoid leaking sensitive information, and b) avoid unexpected render issues once the temporary cookie is deleted. For example, a login function may return a user’s session id to retrieve from your Astro frontmatter, rather than the entire user object.
#11648589d351 Thanks @bholmesdev! - Fixes unexpected error when refreshing a POST request from a form using Actions.
#1160009ec2ca Thanks @ArmandPhilippot! - Deprecates getEntryBySlug and getDataEntryById functions exported by astro:content in favor of getEntry.
#1159381d7150 Thanks @bholmesdev! - Adds support for Date(), Map(), and Set() from action results. See devalue for a complete list of supported values.
Also fixes serialization exceptions when deploying Actions with edge middleware on Netlify and Vercel.
#11617196092a Thanks @abubakriz! - Fix toolbar audit incorrectly flagging images as above the fold.
#116342716f52 Thanks @bholmesdev! - Fixes internal server error when calling an Astro Action without arguments on Vercel.
#116289aaf58c Thanks @madbook! - Ensures consistent CSS chunk hashes across different environments
#11584a65ffe3 Thanks @bholmesdev! - Removes async local storage dependency from Astro Actions. This allows Actions to run in Cloudflare and Stackblitz without opt-in flags or other configuration.
This also introduces a new convention for calling actions from server code. Instead of calling actions directly, you must wrap function calls with the new Astro.callAction() utility.
callAction() is meant to trigger an action from server code. getActionResult() usage with form submissions remains unchanged.
If you call actions directly from server code, update function calls to use the Astro.callAction() wrapper for pages and context.callAction() for endpoints:
---
import { actions } from 'astro:actions';
const result = await actions.searchPosts({ searchTerm: 'test' });
const result = await Astro.callAction(actions.searchPosts, { searchTerm: 'test' });
#11507a62345f Thanks @ematipico! - Adds color-coding to the console output during the build to highlight slow pages.
Pages that take more than 500 milliseconds to render will have their build time logged in red. This change can help you discover pages of your site that are not performant and may need attention.
#11379e5e2d3e Thanks @alexanderniebuhr! - The experimental.contentCollectionJsonSchema feature introduced behind a flag in v4.5.0 is no longer experimental and is available for general use.
If you are working with collections of type data, Astro will now auto-generate JSON schema files for your editor to get IntelliSense and type-checking. A separate file will be created for each data collection in your project based on your collections defined in src/content/config.ts using a library called zod-to-json-schema.
This feature requires you to manually set your schema’s file path as the value for $schema in each data entry file of the collection:
Alternatively, you can set this value in your editor settings. For example, to set this value in VSCode’s json.schemas setting, provide the path of files to match and the location of your JSON schema:
{
"json.schemas": [
{
"fileMatch": ["/src/content/authors/**"],
"url": "./.astro/collections/authors.schema.json"
}
]
}
If you were previously using this feature, please remove the experimental flag from your Astro config:
import { defineConfig } from 'astro'
export default defineConfig({
experimental: {
contentCollectionJsonSchema: true
}
})
If you have been waiting for stabilization before using JSON Schema generation for content collections, you can now do so.
#1154245ad326 Thanks @ematipico! - The experimental.rewriting feature introduced behind a flag in v4.8.0 is no longer experimental and is available for general use.
Astro.rewrite() and context.rewrite() allow you to render a different page without changing the URL in the browser. Unlike using a redirect, your visitor is kept on the original page they visited.
Rewrites can be useful for showing the same content at multiple paths (e.g. /products/shoes/men/ and /products/men/shoes/) without needing to maintain two identical source files.
Rewrites are supported in Astro pages, endpoints, and middleware.
Return Astro.rewrite() in the frontmatter of a .astro page component to display a different page’s content, such as fallback localized content:
src/pages/es-cu/articles/introduction.astro
---
return Astro.rewrite("/es/articles/introduction")
---
Use context.rewrite() in endpoints, for example to reroute to a different page:
src/pages/api.js
exportfunctionGET(context) {
if (!context.locals.allowed) {
return context.rewrite('/');
}
}
The middleware next() function now accepts a parameter with the same type as the rewrite() function. For example, with next("/"), you can call the next middleware function with a new Request.
src/middleware.js
exportfunctiononRequest(context, next) {
if (!context.cookies.get('allowed')) {
returnnext('/'); // new signature
}
returnnext();
}
If you were previously using this feature, please remove the experimental flag from your Astro config:
astro.config.mjs
export default defineConfig({
experimental: {
rewriting: true
}
})
If you have been waiting for stabilization before using rewrites in Astro, you can now do so.
#115711c3265a Thanks @bholmesdev! - BREAKING CHANGE to the experimental Actions API only. Install the latest @astrojs/react integration as well if you’re using React 19 features.
Make .safe() the default return value for actions. This means { data, error } will be returned when calling an action directly. If you prefer to get the data while allowing errors to throw, chain the .orThrow() modifier.
import { actions } from'astro:actions';
// Before
const { data, error } =await actions.like.safe();
// After
const { data, error } =await actions.like();
// Before
constnewLikes=await actions.like();
// After
constnewLikes=await actions.like.orThrow();
To migrate your existing action calls:
Remove .safe from existing safe action calls
Add .orThrow to existing unsafe action calls
#115467f26de9 Thanks @ArmandPhilippot! - Remove “SSR Only” mention in Astro.redirect inline documentation and update reference link.
#115258068131 Thanks @ematipico! - Fixes a case where the build was failing when experimental.actions was enabled, an adapter was in use, and there were not actions inside the user code base.
#11574e3f29d4 Thanks @Princesseuh! - Fixes line with the error not being properly highlighted in the error overlay
#1157084189b6 Thanks @bholmesdev! - BREAKING CHANGE to the experimental Actions API only. Install the latest @astrojs/react integration as well if you’re using React 19 features.
Updates the Astro Actions fallback to support action={actions.name} instead of using getActionProps(). This will submit a form to the server in zero-JS scenarios using a search parameter:
---
import { actions } from'astro:actions';
---
<formaction={actions.logOut}>
<!--output: action="?_astroAction=logOut"-->
<button>Log Out</button>
</form>
You may also construct form action URLs using string concatenation, or by using the URL() constructor, with the an action’s .queryString property:
getActionProps() is now deprecated. To use the new fallback pattern, remove the getActionProps() input from your form and pass your action function to the form action attribute:
#1155302c85b5 Thanks @ematipico! - Fixes an issue in content collection caching, where two documents with the same contents were generating an error during the build.
#114869c0c849 Thanks @ematipico! - Adds a new function called addClientRenderer to the Container API.
This function should be used when rendering components using the client:* directives. The addClientRenderer API must be used
after the use of the addServerRenderer:
This option allows you to override the values of a theme’s inline style, adding only CSS variables to give you more flexibility in applying multiple color themes.
Configure defaultColor: false in your Shiki config to apply throughout your site, or pass to Astro’s built-in <Code> component to style an individual code block.
#113042e70741 Thanks @Fryuni! - Refactors the type for integration hooks so that integration authors writing custom integration hooks can now allow runtime interactions between their integration and other integrations.
This internal change should not break existing code for integration authors.
To declare your own hooks for your integration, extend the Astro.IntegrationHooks interface:
Call your hooks on all other integrations installed in a project at the appropriate time. For example, you can call your hook on initialization before either the Vite or Astro config have resolved:
Server Islands allow you to specify components that should run on the server, allowing the rest of the page to be more aggressively cached, or even generated statically. Turn any .astro component into a server island by adding the server:defer directive and optionally, fallback placeholder content:
The server:defer directive can be used on any Astro component in a project using hybrid or server mode with an adapter. There are no special APIs needed inside of the island.
Enable server islands by adding the experimental flag to your Astro config with an appropriate output mode and adatper:
#114827c9ed71 Thanks @Princesseuh! - Adds a --noSync parameter to the astro check command to skip the type-gen step. This can be useful when running astro check inside packages that have Astro components, but are not Astro projects
#1109836e30a3 Thanks @itsmatteomanf! - Adds a new inferRemoteSize() function that can be used to infer the dimensions of a remote image.
Previously, the ability to infer these values was only available by adding the [inferSize] attribute to the <Image> and <Picture> components or getImage(). Now, you can also access this data outside of these components.
This is useful for when you need to know the dimensions of an image for styling purposes or to calculate different densities for responsive images.
#114777e9c4a1 Thanks @ematipico! - Fixes an issue where the development server was emitting a 404 status code when the user uses a rewrite that emits a 200 status code.
#11479ca969d5 Thanks @florian-lefebvre! - Fixes a case where invalid astro:env variables at runtime would not throw correctly
#11415e9334d0 Thanks @florian-lefebvre! - Refactors how sync works and when it’s called. Fixes an issue with astro:env types in dev not being generated
#114783161b67 Thanks @bluwy! - Supports importing Astro components with Vite queries, like ?url, ?raw, and ?direct
Vercel, and probably other adapters only allow pre-defined routes. This makes it so that the astro:build:done hook includes the _server-islands/ route as part of the route data, which is used to configure available routes.
#11459bc2e74d Thanks @mingjunlu! - Fixes false positive audit warnings on elements with the role “tabpanel”.
#11472cb4e6d0 Thanks @delucis! - Avoids targeting all files in the src/ directory for eager optimization by Vite. After this change, only JSX, Vue, Svelte, and Astro components get scanned for early optimization.
#114376ccb30e Thanks @NuroDev! - Fixes a case where Astro’s config experimental.env.schema keys did not allow numbers. Numbers are still not allowed as the first character to be able to generate valid JavaScript identifiers
#1143908baf56 Thanks @bholmesdev! - Expands the isInputError() utility from astro:actions to accept errors of any type. This should now allow type narrowing from a try / catch block.
#114520e66849 Thanks @FugiTech! - Fixes an issue where using .nullish() in a formdata Astro action would always parse as a string
#11438619f07d Thanks @bholmesdev! - Exposes utility types from astro:actions for the defineAction handler (ActionHandler) and the ActionError code (ActionErrorCode).
#1145617e048d Thanks @RickyC0626! - Fixes astro dev --open unexpected behavior that spawns a new tab every time a config file is saved
#113370a4b31f Thanks @florian-lefebvre! - Adds a new property experimental.env.validateSecrets to allow validating private variables on the server.
By default, this is set to false and only public variables are checked on start. If enabled, secrets will also be checked on start (dev/build modes). This is useful for example in some CIs to make sure all your secrets are correctly set before deploying.
#11443ea4bc04 Thanks @bholmesdev! - Expose new ActionReturnType utility from astro:actions. This infers the return type of an action by passing typeof actions.name as a type argument. This example defines a like action that returns likes as an object:
actions/index.ts
import { defineAction } from'astro:actions';
exportconstserver= {
like: defineAction({
handler: () => {
/* ... */
return { likes: 42 };
},
}),
};
In your client code, you can infer this handler return value with ActionReturnType:
#1136293993b7 Thanks @ematipico! - Fixes an issue where creating manually the i18n middleware could break the logic of the functions of the virtual module astro:i18n
#1134998d9ce4 Thanks @ematipico! - Fixes an issue where Astro didn’t throw an error when Astro.rewrite was used without providing the experimental flag
#11352a55ee02 Thanks @ematipico! - Fixes an issue where the rewrites didn’t update the status code when using manual i18n routing.
#113270df8142 Thanks @ematipico! - Fixes an issue with the container APIs where a runtime error was thrown during the build, when using pnpm as package manager.
#1132641121fb Thanks @florian-lefebvre! - Fixes a case where running astro sync when using the experimental astro:env feature would fail if environment variables were missing
#113389752a0b Thanks @zaaakher! - Fixes svg icon margin in devtool tooltip title to look coherent in rtl and ltr layouts
Previously we tracked non-fatal errors in telemetry to get a good idea of the types of errors that occur in astro dev. However this has become noisy over time and results in a lot of data that isn’t particularly useful. This removes those non-fatal errors from being tracked.
#1130844c61dd Thanks @ematipico! - Fixes an issue where custom 404.astro and 500.astro were not returning the correct status code when rendered inside a rewriting cycle.
#113020622567 Thanks @martrapp! - Fixes an issue with the view transition router when redirecting to an URL with different origin.