#126458704c54 Thanks @sarah11918! - Updates some reference links in error messages for new v5 docs.
#1264148ca399 Thanks @ascorbic! - Fixes a bug where astro info --copy wasn’t working correctly on macOS systems.
#1246162939ad Thanks @kyr0! - Removes the misleading log message telling that a custom renderer is not recognized while it clearly is and works.
#12642ff18b9c Thanks @ematipico! - Provides more information when logging a warning for accessing Astro.request.headers in prerendered pages
#1263403958d9 Thanks @delucis! - Improves error message formatting for user config and content collection frontmatter
#125476b6e18d Thanks @mtwilliams-code! - Fixes a bug where URL search parameters weren’t passed when using the i18n fallback feature.
#12449e6b8017 Thanks @apatel369! - Fixes an issue where the custom assetFileNames configuration caused assets to be incorrectly moved to the server directory instead of the client directory, resulting in 404 errors when accessed from the client side.
#12518e216250 Thanks @ematipico! - Fixes an issue where SSR error pages would return duplicated custom headers.
#1262574bfad0 Thanks @ematipico! - Fixes an issue where the experimental.svg had incorrect type, resulting in some errors in the editors.
#12631dec0305 Thanks @ascorbic! - Fixes a bug where the class attribute was rendered twice on the image component
#126230e4fecb Thanks @ascorbic! - Correctly handles images in content collections with uppercase file extensions
#126338a551c1 Thanks @bluwy! - Cleans up content layer sync during builds and programmatic sync() calls
#1264022e405a Thanks @ascorbic! - Fixes a bug that caused content collections to be returned empty when run in a test environment
#12613306c9f9 Thanks @matthewp! - Fix use of cloned requests in middleware with clientAddress
When using context.clientAddress or Astro.clientAddress Astro looks up the address in a hidden property. Cloning a request can cause this hidden property to be lost.
The fix is to pass the address as an internal property instead, decoupling it from the request.
The previously experimental feature globalRoutePriority is now the default in Astro 5.
This was a refactoring of route prioritization in Astro, making it so that injected routes, file-based routes, and redirects are all prioritized using the same logic. This feature has been enabled for all Starlight projects since it was added and should not affect most users.
#11864ee38b3a Thanks @ematipico! - ### [changed]: entryPoint type inside the hook astro:build:ssr
In Astro v4.x, the entryPoint type was RouteData.
Astro v5.0 the entryPoint type is IntegrationRouteData, which contains a subset of the RouteData type. The fields isIndex and fallbackRoutes were removed.
What should I do?
Update your adapter to change the type of entryPoint from RouteData to IntegrationRouteData.
import type {RouteData} from 'astro';
import type {IntegrationRouteData} from "astro"
function useRoute(route: RouteData) {
function useRoute(route: IntegrationRouteData) {
}
#125249f44019 Thanks @bluwy! - Bumps Vite to ^6.0.1 and handles its breaking changes
#10742b6fbdaa Thanks @ematipico! - The lowest version of Node supported by Astro is now Node v18.17.1 and higher.
#1191646ea29f Thanks @bluwy! - Updates how the build.client and build.server option values get resolved to match existing documentation. With this fix, the option values will now correctly resolve relative to the outDir option. So if outDir is set to ./dist/nested/, then by default:
build.client will resolve to <root>/dist/nested/client/
build.server will resolve to <root>/dist/nested/server/
Previously the values were incorrectly resolved:
build.client was resolved to <root>/dist/nested/dist/client/
build.server was resolved to <root>/dist/nested/dist/server/
If you were relying on the previous build paths, make sure that your project code is updated to the new build paths.
#11982d84e444 Thanks @Princesseuh! - Adds a default exclude and include value to the tsconfig presets. {projectDir}/dist is now excluded by default, and {projectDir}/.astro/types.d.ts and {projectDir}/**/* are included by default.
Both of these options can be overridden by setting your own values to the corresponding settings in your tsconfig.json file.
#118613ab3b4e Thanks @bluwy! - Cleans up Astro-specfic metadata attached to vfile.data in Remark and Rehype plugins. Previously, the metadata was attached in different locations with inconsistent names. The metadata is now renamed as below:
The types of imagePaths has also been updated from Set<string> to string[]. The vfile.data.astro.frontmatter metadata is left unchanged.
While we don’t consider these APIs public, they can be accessed by Remark and Rehype plugins that want to re-use Astro’s metadata. If you are using these APIs, make sure to access them in the new locations.
Middleware, API endpoints, and pages can no longer override the locals object in its entirety. You can still append values onto the object, but you can not replace the entire object and delete its existing values.
If you were previously overwriting like so:
ctx.locals = {
one: 1,
two: 2,
};
This can be changed to an assignment on the existing object instead:
Object.assign(ctx.locals, {
one: 1,
two: 2,
});
#11908518433e Thanks @Princesseuh! - The image.endpoint config now allow customizing the route of the image endpoint in addition to the entrypoint. This can be useful in niche situations where the default route /_image conflicts with an existing route or your local server setup.
import { defineConfig } from'astro/config';
defineConfig({
image: {
endpoint: {
route: '/image',
entrypoint: './src/image_endpoint.ts',
},
},
});
#120085608338 Thanks @Princesseuh! - Welcome to the Astro 5 beta! This release has no changes from the latest alpha of this package, but it does bring us one step closer to the final, stable release.
Starting from this release, no breaking changes will be introduced unless absolutely necessary.
#11679ea71b90 Thanks @florian-lefebvre! - The astro:env feature introduced behind a flag in v4.10.0 is no longer experimental and is available for general use. If you have been waiting for stabilization before using astro:env, you can now do so.
This feature lets you configure a type-safe schema for your environment variables, and indicate whether they should be available on the server or the client.
To configure a schema, add the env option to your Astro config and define your client and server variables. If you were previously using this feature, please remove the experimental flag from your Astro config and move your entire env configuration unchanged to a top-level option.
#11806f7f2338 Thanks @Princesseuh! - Removes the assets property on supportedAstroFeatures for adapters, as it did not reflect reality properly in many cases.
Now, relating to assets, only a single sharpImageService property is available, determining if the adapter is compatible with the built-in sharp image service.
#11864ee38b3a Thanks @ematipico! - ### [changed]: routes type inside the hook astro:build:done
In Astro v4.x, the routes type was RouteData.
Astro v5.0 the routes type is IntegrationRouteData, which contains a subset of the RouteData type. The fields isIndex and fallbackRoutes were removed.
What should I do?
Update your adapter to change the type of routes from RouteData to IntegrationRouteData.
import type {RouteData} from 'astro';
import type {IntegrationRouteData} from "astro"
function useRoute(route: RouteData) {
function useRoute(route: IntegrationRouteData) {
}
#11941b6a5f39 Thanks @Princesseuh! - Merges the output: 'hybrid' and output: 'static' configurations into one single configuration (now called 'static') that works the same way as the previous hybrid option.
It is no longer necessary to specify output: 'hybrid' in your Astro config to use server-rendered pages. The new output: 'static' has this capability included. Astro will now automatically provide the ability to opt out of prerendering in your static site with no change to your output configuration required. Any page route or endpoint can include export const prerender = false to be server-rendered, while the rest of your site is statically-generated.
If your project used hybrid rendering, you must now remove the output: 'hybrid' option from your Astro config as it no longer exists. However, no other changes to your project are required, and you should have no breaking changes. The previous 'hybrid' behavior is now the default, under a new name 'static'.
If you were using the output: 'static' (default) option, you can continue to use it as before. By default, all of your pages will continue to be prerendered and you will have a completely static site. You should have no breaking changes to your project.
import { defineConfig } from "astro/config";
export default defineConfig({
output: 'hybrid',
});
An adapter is still required to deploy an Astro project with any server-rendered pages. Failure to include an adapter will result in a warning in development and an error at build time.
#117887c0ccfc Thanks @ematipico! - Updates the default value of security.checkOrigin to true, which enables Cross-Site Request Forgery (CSRF) protection by default for pages rendered on demand.
If you had previously configured security.checkOrigin: true, you no longer need this set in your Astro config. This is now the default and it is safe to remove.
To disable this behavior and opt out of automatically checking that the “origin” header matches the URL sent by each request, you must explicitly set security.checkOrigin: false:
export default defineConfig({
security: {
checkOrigin: false
}
})
#11825560ef15 Thanks @bluwy! - Updates internal Shiki rehype plugin to highlight code blocks as hast (using Shiki’s codeToHast() API). This allows a more direct Markdown and MDX processing, and improves the performance when building the project, but may cause issues with existing Shiki transformers.
If you are using Shiki transformers passed to markdown.shikiConfig.transformers, you must make sure they do not use the postprocess hook as it no longer runs on code blocks in .md and .mdx files. (See the Shiki documentation on transformer hooks for more information).
Code blocks in .mdoc files and <Code /> component do not use the internal Shiki rehype plugin and are unaffected.
#122684e9a3ac Thanks @ematipico! - The command astro add vercel now updates the configuration file differently, and adds @astrojs/vercel as module to import.
This is a breaking change because it requires the version 8.* of @astrojs/vercel.
#117416617491 Thanks @bluwy! - Removes internal JSX handling and moves the responsibility to the @astrojs/mdx package directly. The following exports are also now removed:
astro/jsx/babel.js
astro/jsx/component.js
astro/jsx/index.js
astro/jsx/renderer.js
astro/jsx/server.js
astro/jsx/transform-options.js
If your project includes .mdx files, you must upgrade @astrojs/mdx to the latest version so that it doesn’t rely on these entrypoints to handle your JSX.
#117829a2aaa0 Thanks @Princesseuh! - Makes the compiledContent property of Markdown content an async function, this change should fix underlying issues where sometimes when using a custom image service and images inside Markdown, Node would exit suddenly without any error message.
---
import * as myPost from "../post.md";
const content = myPost.compiledContent();
const content = await myPost.compiledContent();
---
<Fragment set:html={content} />
#118192bdde80 Thanks @bluwy! - Updates the Astro config loading flow to ignore processing locally-linked dependencies with Vite (e.g. npm link, in a monorepo, etc). Instead, they will be normally imported by the Node.js runtime the same way as other dependencies from node_modules.
Previously, Astro would process locally-linked dependencies which were able to use Vite features like TypeScript when imported by the Astro config file.
However, this caused confusion as integration authors may test against a package that worked locally, but not when published. This method also restricts using CJS-only dependencies because Vite requires the code to be ESM. Therefore, Astro’s behaviour is now changed to ignore processing any type of dependencies by Vite.
In most cases, make sure your locally-linked dependencies are built to JS before running the Astro project, and the config loading should work as before.
Usage of astro:content in the client has always been discouraged because it leads to all of your content winding up in your client bundle, and can possibly leaks secrets.
This formally makes doing so impossible, adding to the previous warning with errors.
In the future Astro might add APIs for client-usage based on needs.
#11979423dfc1 Thanks @bluwy! - Bumps vite dependency to v6.0.0-beta.2. The version is pinned and will be updated as new Vite versions publish to prevent unhandled breaking changes. For the full list of Vite-specific changes, see its changelog.
#118593804711 Thanks @florian-lefebvre! - Changes the default tsconfig.json with better defaults, and makes src/env.d.ts optional
Astro’s default tsconfig.json in starter examples has been updated to include generated types and exclude your build output. This means that src/env.d.ts is only necessary if you have added custom type declarations or if you’re not using a tsconfig.json file.
Additionally, running astro sync no longer creates, nor updates, src/env.d.ts as it is not required for type-checking standard Astro projects.
To update your project to Astro’s recommended TypeScript settings, please add the following include and exclude properties to tsconfig.json:
{
"extends": "astro/tsconfigs/base",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"]
}
#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.
#12551abf9a89 Thanks @ematipico! - Refactors legacy content and data collections to use the Content Layer API glob() loader for better performance and to support backwards compatibility. Also introduces the legacy.collections flag for projects that are unable to update to the new behavior immediately.
:warning: BREAKING CHANGE FOR LEGACY CONTENT COLLECTIONS :warning:
By default, collections that use the old types (content or data) and do not define a loader are now implemented under the hood using the Content Layer API’s built-in glob() loader, with extra backward-compatibility handling.
In order to achieve backwards compatibility with existing content collections, the following have been implemented:
a glob loader collection is defined, with patterns that match the previous handling (matches src/content/<collection name>/**/*.md and other content extensions depending on installed integrations, with underscore-prefixed files and folders ignored)
When used in the runtime, the entries have an ID based on the filename in the same format as legacy collections
A slug field is added with the same format as before
A render() method is added to the entry, so they can be called using entry.render()
getEntryBySlug is supported
In order to achieve backwards compatibility with existing data collections, the following have been implemented:
a glob loader collection is defined, with patterns that match the previous handling (matches src/content/<collection name>/**/*{.json,.yaml} and other data extensions, with underscore-prefixed files and folders ignored)
Entries have an ID that is not slugified
getDataEntryById is supported
While this backwards compatibility implementation is able to emulate most of the features of legacy collections, there are some differences and limitations that may cause breaking changes to existing collections:
In previous versions of Astro, collections would be generated for all folders in src/content/, even if they were not defined in src/content/config.ts. This behavior is now deprecated, and collections should always be defined in src/content/config.ts. For existing collections, these can just be empty declarations (e.g. const blog = defineCollection({})) and Astro will implicitly define your legacy collection for you in a way that is compatible with the new loading behavior.
The special layout field is not supported in Markdown collection entries. This property is intended only for standalone page files located in src/pages/ and not likely to be in your collection entries. However, if you were using this property, you must now create dynamic routes that include your page styling.
Sort order of generated collections is non-deterministic and platform-dependent. This means that if you are calling getCollection(), the order in which entries are returned may be different than before. If you need a specific order, you should sort the collection entries yourself.
image().refine() is not supported. If you need to validate the properties of an image you will need to do this at runtime in your page or component.
the key argument of getEntry(collection, key) is typed as string, rather than having types for every entry.
A new legacy configuration flag legacy.collections is added for users that want to keep their current legacy (content and data) collections behavior (available in Astro v2 - v4), or who are not yet ready to update their projects:
astro.config.mjs
import { defineConfig } from'astro/config';
exportdefaultdefineConfig({
legacy: {
collections: true,
},
});
When set, no changes to your existing collections are necessary, and the restrictions on storing both new and old collections continue to exist: legacy collections (only) must continue to remain in src/content/, while new collections using a loader from the Content Layer API are forbidden in that folder.
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:
el.getAttribute('inherit') === ''
el.getAttribute('inherit') === 'false'
el.hasAttribute('data-light')
el.dataset.light === 'true'
#11770cfa6a47 Thanks @Princesseuh! - Removed support for the Squoosh image service. As the underlying library libsquoosh is no longer maintained, and the image service sees very little usage we have decided to remove it from Astro.
Our recommendation is to use the base Sharp image service, which is more powerful, faster, and more actively maintained.
import { squooshImageService } from "astro/config";
#1223190ae100 Thanks @bluwy! - Updates the automatic charset=utf-8 behavior for Markdown pages, where instead of responding with charset=utf-8 in the Content-Type header, Astro will now automatically add the <meta charset="utf-8"> tag instead.
This behaviour only applies to Markdown pages (.md or similar Markdown files located within src/pages/) that do not use Astro’s special layout frontmatter property. It matches the rendering behaviour of other non-content pages, and retains the minimal boilerplate needed to write with non-ASCII characters when adding individual Markdown pages to your site.
If your Markdown pages use the layout frontmatter property, then HTML encoding will be handled by the designated layout component instead, and the <meta charset="utf-8"> tag will not be added to your page by default.
If you require charset=utf-8 to render your page correctly, make sure that your layout components contain the <meta charset="utf-8"> tag. You may need to add this if you have not already done so.
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.
#11864ee38b3a Thanks @ematipico! - ### [changed]: RouteData.distURL is now an array
In Astro v4.x, RouteData.distURL was undefined or a URL
Astro v5.0, RouteData.distURL is undefined or an array of URL. This was a bug, because a route can generate multiple files on disk, especially when using dynamic routes such as [slug] or [...slug].
What should I do?
Update your code to handle RouteData.distURL as an array.
if (route.distURL) {
if (route.distURL.endsWith('index.html')) {
// do something
}
for (const url of route.distURL) {
if (url.endsWith('index.html')) {
// do something
}
}
}
#112534e5cc5a Thanks @kevinzunigacuellar! - Changes the data returned for page.url.current, page.url.next, page.url.prev, page.url.first and page.url.last to include the value set for base in your Astro config.
Previously, you had to manually prepend your configured value for base to the URL path. Now, Astro automatically includes your base value in next and prev URLs.
If you are using the paginate() function for “previous” and “next” URLs, remove any existing base value as it is now added for you:
---
export async function getStaticPaths({ paginate }) {
const astronautPages = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
astronaut: 'Sally Ride',
}, {
astronaut: 'John Glenn',
}];
return paginate(astronautPages, { pageSize: 1 });
}
const { page } = Astro.props;
// `base: /'docs'` configured in `astro.config.mjs`
const prev = "/docs" + page.url.prev;
const prev = page.url.prev;
---
<a id="prev" href={prev}>Back</a>
#120797febf1f Thanks @ematipico! - params passed in getStaticPaths are no longer automatically decoded.
[changed]: params aren’t decoded anymore.
In Astro v4.x, params in were automatically decoded using decodeURIComponent.
Astro v5.0 doesn’t automatically decode params in getStaticPaths anymore, so you’ll need to manually decode them yourself if needed
What should I do?
If you were relying on the automatic decode, you’ll need to manually decode it using decodeURI.
Note that the use of decodeURIComponent) is discouraged for getStaticPaths because it decodes more characters than it should, for example /, ?, # and more.
---
export function getStaticPaths() {
return [
{ params: { id: decodeURI("%5Bpage%5D") } },
{ params: { id: "%5Bpage%5D" } },
]
}
const { id } = Astro.params;
---
🍿 Minor Changes
#11941b6a5f39 Thanks @Princesseuh! - Adapters can now specify the build output type they’re intended for using the adapterFeatures.buildOutput property. This property can be used to always generate a server output, even if the project doesn’t have any server-rendered pages.
If your adapter specifies buildOutput: 'static', and the user’s project contains server-rendered pages, Astro will warn in development and error at build time. Note that a hybrid output, containing both static and server-rendered pages, is considered to be a server output, as a server is required to serve the server-rendered pages.
#12067c48916c Thanks @stramel! - Adds experimental support for built-in SVG components.
This feature allows you to import SVG files directly into your Astro project as components. By default, Astro will inline the SVG content into your HTML output.
To enable this feature, set experimental.svg to true in your Astro config:
{
experimental: {
svg: true,
},
}
To use this feature, import an SVG file in your Astro project, passing any common SVG attributes to the imported component. Astro also provides a size attribute to set equal height and width properties:
---
import Logo from'./path/to/svg/file.svg';
---
<Logosize={24} />
For a complete overview, and to give feedback on this experimental API, see the Feature RFC.
#1222651d13e2 Thanks @ematipico! - The following renderer fields and integration fields now accept URL as a type:
#12243eb41d13 Thanks @florian-lefebvre! - Improves defineConfig type safety. TypeScript will now error if a group of related configuration options do not have consistent types. For example, you will now see an error if your language set for i18n.defaultLocale is not one of the supported locales specified in i18n.locales.
#123298309c61 Thanks @florian-lefebvre! - Adds a new astro:routes:resolved hook to the Integration API. Also update the astro:build:done hook by deprecating routes and adding a new assets map.
When building an integration, you can now get access to routes inside the astro:routes:resolved hook:
constintegration= () => {
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': ({ routes }) => {
console.log(routes);
},
},
};
};
This hook runs before astro:config:done, and whenever a route changes in development.
The routes array from astro:build:done is now deprecated, and exposed properties are now available on astro:routes:resolved, except for distURL. For this, you can use the newly exposed assets map:
const integration = () => {
let routes
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': (params) => {
routes = params.routes
},
'astro:build:done': ({
routes
assets
}) => {
for (const route of routes) {
const distURL = assets.get(route.pattern)
if (distURL) {
Object.assign(route, { distURL })
}
}
console.log(routes)
}
}
}
}
#11911c3dce83 Thanks @ascorbic! - The Content Layer API introduced behind a flag in 4.14.0 is now stable and ready for use in Astro v5.0.
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. For more details, see the Content Layer RFC.
If you previously used this feature, you can now remove the experimental.contentLayer flag from your Astro config:
astro.config.mjs
import { defineConfig } from 'astro'
export default defineConfig({
experimental: {
contentLayer: true
}
})
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:
The <ViewTransitions /> component has been renamed to <ClientRouter />. There are no other changes than the name. The old name will continue to work in Astro 5.x, but will be removed in 6.0.
This change was done to clarify the role of the component within Astro’s View Transitions support. Astro supports View Transitions APIs in a few different ways, and renaming the component makes it more clear that the features you get from the ClientRouter component are slightly different from what you get using the native CSS-based MPA router.
We still intend to maintain the ClientRouter as before, and it’s still important for use-cases that the native support doesn’t cover, such as persisting state between pages.
#11875a8a3d2c Thanks @florian-lefebvre! - Adds a new property isPrerendered to the globals Astro and APIContext . This boolean value represents whether or not the current page is prerendered:
src/pages/index.astro
---
exportconstprerender=true;
---
src/middleware.js
exportconstonRequest= (ctx, next) => {
console.log(ctx.isPrerendered); // it will log true
returnnext();
};
#1204721b5e80 Thanks @rgodha24! - Adds a new optional parser property to the built-in file() loader for content collections to support additional file types such as toml and csv.
The file() loader now accepts a second argument that defines a parser function. This allows you to specify a custom parser (e.g. toml.parse or csv-parse) to create a collection from a file’s contents. The file() loader will automatically detect and parse JSON and YAML files (based on their file extension) with no need for a parser.
This works with any type of custom file formats including csv and toml. The following example defines a content collection dogs using a .toml file.
[[dogs]]
id = "..."
age = "..."
[[dogs]]
id = "..."
age = "..."
After importing TOML’s parser, you can load the dogs collection into your project by passing both a file path and parser to the file() loader.
The parser argument also allows you to load a single collection from a nested JSON document. For example, this JSON file contains multiple collections:
{ "dogs": [{}], "cats": [{}] }
You can seperate these collections by passing a custom parser to the file() loader like so:
#1169805139ef Thanks @ematipico! - Adds a new property to the globals Astro and APIContext called routePattern. The routePattern represents the current route (component)
that is being rendered by Astro. It’s usually a path pattern will look like this: blog/[slug]:
src/pages/blog/[slug].astro
---
constroute= Astro.routePattern;
console.log(route); // it will log "blog/[slug]"
---
src/pages/index.js
exportconstGET= (ctx) => {
console.log(ctx.routePattern); // it will log src/pages/index.js
returnnew Response.json({ loreum: 'ipsum' });
};
#11941b6a5f39 Thanks @Princesseuh! - Adds a new buildOutput property to the astro:config:done hook returning the build output type.
This can be used to know if the user’s project will be built as a static site (HTML files), or a server-rendered site (whose exact output depends on the adapter).
#12377af867f3 Thanks @ascorbic! - Adds experimental support for automatic responsive images
This feature is experimental and may change in future versions. To enable it, set experimental.responsiveImages to true in your astro.config.mjs file.
astro.config.mjs
{
experimental: {
responsiveImages: true,
},
}
When this flag is enabled, you can pass a layout prop to any <Image /> or <Picture /> component to create a responsive image. When a layout is set, images have automatically generated srcset and sizes attributes based on the image’s dimensions and the layout type. Images with responsive and full-width layouts will have styles applied to ensure they resize according to their container.
---
import { Image, Picture } from'astro:assets';
import myImage from'../assets/my_image.png';
---
<Image
src={myImage}
alt="A description of my image."
layout="responsive"
width={800}
height={600}
/>
<Picture
src={myImage}
alt="A description of my image."
layout="full-width"
formats={['avif', 'webp', 'jpeg']}
/>
This <Image /> component will generate the following HTML output:
These are additional properties available to the <Image /> and <Picture /> components when responsive images are enabled:
layout: The layout type for the image. Can be responsive, fixed, full-width or none. Defaults to value of image.experimentalLayout.
fit: Defines how the image should be cropped if the aspect ratio is changed. Values match those of CSS object-fit. Defaults to cover, or the value of image.experimentalObjectFit if set.
position: Defines the position of the image crop if the aspect ratio is changed. Values match those of CSS object-position. Defaults to center, or the value of image.experimentalObjectPosition if set.
priority: If set, eagerly loads the image. Otherwise images will be lazy-loaded. Use this for your largest above-the-fold image. Defaults to false.
Default responsive image settings
You can enable responsive images for all <Image /> and <Picture /> components by setting image.experimentalLayout with a default value. This can be overridden by the layout prop on each component.
Example:
astro.config.mjs
{
image: {
// Used for all `<Image />` and `<Picture />` components unless overridden
experimentalLayout: 'responsive',
},
experimental: {
responsiveImages: true,
},
}
---
import { Image } from'astro:assets';
import myImage from'../assets/my_image.png';
---
<Imagesrc={myImage} alt="This will use responsive layout"width={800} height={600} />
<Imagesrc={myImage} alt="This will use full-width layout"layout="full-width" />
<Imagesrc={myImage} alt="This will disable responsive images"layout="none" />
For a complete overview, and to give feedback on this experimental API, see the Responsive Images RFC.
#1215093351bc Thanks @bluwy! - Adds support for passing values other than "production" or "development" to the --mode flag (e.g. "staging", "testing", or any custom value) to change the value of import.meta.env.MODE or the loaded .env file. This allows you take advantage of Vite’s mode feature.
Also adds a new --devOutput flag for astro build that will output a development-based build.
Note that changing the mode does not change the kind of code transform handled by Vite and Astro:
In astro dev, Astro will transform code with debug information.
In astro build, Astro will transform code with the most optimized output and removes debug information.
In astro build --devOutput (new flag), Astro will transform code with debug information like in astro dev.
This enables various usecases like:
Terminal window
# Run the dev server connected to a "staging" API
astrodev--modestaging
# Build a site that connects to a "staging" API
astrobuild--modestaging
# Build a site that connects to a "production" API with additional debug information
astrobuild--devOutput
# Build a site that connects to a "testing" API
astrobuild--modetesting
The different modes can be used to load different .env files, e.g. .env.staging or .env.production, which can be customized for each environment, for example with different API_URL environment variable values.
#1251014feaf3 Thanks @bholmesdev! - Changes the generated URL query param from _astroAction to _action when submitting a form using Actions. This avoids leaking the framework name into the URL bar, which may be considered a security issue.
#11806f7f2338 Thanks @Princesseuh! - The value of the different properties on supportedAstroFeatures for adapters can now be objects, with a support and message properties. The content of the message property will be shown in the Astro CLI when the adapter is not compatible with the feature, allowing one to give a better informational message to the user.
This is notably useful with the new limited value, to explain to the user why support is limited.
#1207161d248e Thanks @Princesseuh! - astro add no longer automatically sets output: 'server'. Since the default value of output now allows for server-rendered pages, it no longer makes sense to default to full server builds when you add an adapter
Server islands are Astro’s solution for highly cacheable pages of mixed static and dynamic content. They 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. It will be rendered dynamically at runtime outside the context of the rest of the page, allowing you to add longer cache headers for the pages, or even prerender them.
#12373d10f918 Thanks @bholmesdev! - Changes the default behavior for Astro Action form requests to a standard POST submission.
In Astro 4.x, actions called from an HTML form would trigger a redirect with the result forwarded using cookies. This caused issues for large form errors and return values that exceeded the 4 KB limit of cookie-based storage.
Astro 5.0 now renders the result of an action as a POST result without any forwarding. This will introduce a “confirm form resubmission?” dialog when a user attempts to refresh the page, though it no longer imposes a 4 KB limit on action return value.
We recommend using a session storage provider as described in our Netlify Blob example. However, if you prefer the cookie forwarding behavior from 4.X and accept the 4 KB size limit, you can implement the pattern as shown in this sample snippet:
thrownewError('Internal: Referer unexpectedly missing from Action POST request.');
}
return context.redirect(referer);
}
// Redirect to the destination page on success
return context.redirect(context.originPathname);
}
returnnext();
});
#124753f02d5f Thanks @ascorbic! - Changes the default content config location from src/content/config.* to src/content.config.*.
The previous location is still supported, and is required if the legacy.collections flag is enabled.
#119630a1036e Thanks @florian-lefebvre! - Adds a new createCodegenDir() function to the astro:config:setup hook in the Integrations API
In 4.14, we introduced the injectTypes utility on the astro:config:done hook. It can create .d.ts files and make their types available to user’s projects automatically. Under the hood, it creates a file in <root>/.astro/integrations/<normalized_integration_name>.
While the .astro directory has always been the preferred place to write code generated files, it has also been prone to mistakes. For example, you can write a .astro/types.d.ts file, breaking Astro types. Or you can create a file that overrides a file created by another integration.
In this release, <root>/.astro/integrations/<normalized_integration_name> can now be retrieved in the astro:config:setup hook by calling createCodegenDir(). It allows you to have a dedicated folder, avoiding conflicts with another integration or Astro itself. This directory is created by calling this function so it’s safe to write files to it directly:
#1237994f4fe8 Thanks @Princesseuh! - Adds a new components exported from astro/components: Welcome, to be used by the new Basics template
#11806f7f2338 Thanks @Princesseuh! - Adds a new limited value for the different properties of supportedAstroFeatures for adapters, which indicates that the adapter is compatible with the feature, but with some limitations. This is useful for adapters that support a feature, but not in all cases or with all options.
When importing astro/config, types from astro/client will be made automatically available to your project. If your project tsconfig.json changes how references behave, you’ll still have access to these types after running astro sync.
Astro Content Layer API independently solves some of the caching and performance issues with legacy content collections that this strategy attempted to address. This feature has been replaced with continued work on improvements to the content layer. If you were using this experimental feature, you must now remove the flag from your Astro config as it no longer exists:
export default defineConfig({
experimental: {
contentCollectionsCache: true
}
})
The cacheManifest boolean argument is no longer passed to the astro:build:done integration hook:
const integration = {
name: "my-integration",
hooks: {
"astro:build:done": ({
cacheManifest,
logger
}) => {}
}
}
🐞 Patch Changes
#1256597f413f Thanks @ascorbic! - Fixes a bug where content types were not generated when first running astro dev unless src/content exists
The signature for app.render() has changed, and the second argument is now an options object called renderOptions with more options for customizing rendering.
The renderOptions are:
addCookieHeader: Determines whether Astro will set the Set-Cookie header, otherwise the adapter is expected to do so itself.
clientAddress: The client IP address used to set Astro.clientAddress.
locals: An object of locals that’s set to Astro.locals.
routeData: An object specifying the route to use.
#1252233b0e30 Thanks @ascorbic! - Fixes a bug where content config was ignored if it was outside of content dir and has a parent dir with an underscore
#124244364bff Thanks @ematipico! - Fixes an issue where an incorrect usage of Astro actions was lost when porting the fix from v4 to v5
#12438c8f877c Thanks @ascorbic! - Fixes a bug where legacy content types were generated for content layer collections if they were in the content directory
#119604410130 Thanks @ascorbic! - Fixes an issue where the refresh context data was not passed correctly to content layer loaders
#11878334948c Thanks @ascorbic! - Adds a new function refreshContent to the astro:server:setup hook that allows integrations to refresh the content layer. This can be used, for example, to register a webhook endpoint during dev, or to open a socket to a CMS to listen for changes.
By default, refreshContent will refresh all collections. You can optionally pass a loaders property, which is an array of loader names. If provided, only collections that use those loaders will be refreshed. For example, A CMS integration could use this property to only refresh its own collections.
You can also pass a context object to the loaders. This can be used to pass arbitrary data, such as the webhook body, or an event from the websocket.
#1257807b9ca8 Thanks @WesSouza! - Explicitly import index.ts to fix types when moduleResolution is NodeNext
#117919393243 Thanks @bluwy! - Updates Astro’s default <script> rendering strategy and removes the experimental.directRenderScript option as this is now the default behavior: scripts are always rendered directly. This new strategy prevents scripts from being executed in pages where they are not used.
Scripts will directly render as declared in Astro files (including existing features like TypeScript, importing node_modules, and deduplicating scripts). You can also now conditionally render scripts in your Astro file.
However, this means scripts are no longer hoisted to the <head>, multiple scripts on a page are no longer bundled together, and the <script> tag may interfere with the CSS styling.
As this is a potentially breaking change to your script behavior, please review your <script> tags and ensure that they behave as expected.
#12011cfdaab2 Thanks @ArmandPhilippot! - Fixes a type and an example in documenting the security.checkOrigin property of Astro config.
Server Island requests include the props used to render the island as well as any slots passed in (excluding the fallback slot). Since browsers have a max 4mb URL length we default to using a POST request to avoid overflowing this length.
However in reality most usage of Server Islands are fairly isolated and won’t exceed this limit, so a GET request is possible by passing this same information via search parameters.
Using GET means we can also include a <link rel="preload"> tag to speed up the request.
This change implements this, with safe fallback to POST.
#1195250a0146 Thanks @ascorbic! - Adds support for array patterns in the built-in glob() content collections loader
The glob loader can now accept an array of multiple patterns as well as string patterns. This allows you to more easily combine multiple patterns into a single collection, and also means you can use negative matches to exclude files from the collection.
constprobes=defineCollection({
// Load all markdown files in the space-probes directory, except for those that start with "voyager-"
#12022ddc3a08 Thanks @Princesseuh! - Properly handle including trailing slash on the image endpoint route based on the trailingSlash config
#1216915fa9ba Thanks @ematipico! - Fixes a bug where configured redirects were incorrectly constructed when reading the file system.
This caused an issue where configuring a redirect in astro.config.mjs like { /old: /new }, failed to trigger the correct redirect in the dev server.
#11914b5d827b Thanks @ascorbic! - Exports types for all LoaderContext properties from astro/loaders to make it easier to use them in custom loaders.
The ScopedDataStore interface (which was previously internal) is renamed to DataStore, to reflect the fact that it’s the only public API for the data store.
#1227025192a0 Thanks @ematipico! - Fixes a bug where the params weren’t correctly computed when rendering URLs with non-English characters
#119275b4e3ab Thanks @florian-lefebvre! - Updates the env configuration reference docs to include a full API reference for envField.
#12591b731b3d Thanks @ascorbic! - Fixes a bug where a catchall route would match an image endpoint request
#12339bdb75a8 Thanks @ematipico! - Adds an error when Astro.rewrite() is used to rewrite an on-demand route with a static route when using the "server" output.
This is a forbidden rewrite because Astro can’t retrieve the emitted static route at runtime. This route is served by the hosting platform, and not Astro itself.
#11943fa4671c Thanks @sarah11918! - Updates error messages that assume content collections are located in src/content/ with more generic language
#1203010a756a Thanks @ascorbic! - Resolves image paths in content layer with initial slash as project-relative
When using the image() schema helper, previously paths with an initial slash were treated as public URLs. This was to match the behavior of markdown images. However this is a change from before, where paths with an initial slash were treated as project-relative. This change restores the previous behavior, so that paths with an initial slash are treated as project-relative.
#1255215f000c Thanks @avanderbergh! - Fixed an issue where modifying the Request.headers prototype during prerendering caused a build error. Removed conflicting value and writable properties from the headers descriptor to prevent Invalid property descriptor errors.
#120709693ad4 Thanks @ematipico! - Fixes an issue where the check origin middleware was incorrectly injected when the build output was "static"
#1216915fa9ba Thanks @ematipico! - Fixes a bug where the dev server was not providing a consistent user experience for configured redirects.
With the fix, when you configure a redirect in astro.config.mjs like this { /old: "/new" }, the dev server return an HTML response that matches the one emitted by a static build.
#1251014feaf3 Thanks @bholmesdev! - Changes the generated URL query param from _astroAction to _action when submitting a form using Actions. This avoids leaking the framework name into the URL bar, which may be considered a security issue.
🐞 Patch Changes
#1252233b0e30 Thanks @ascorbic! - Fixes a bug where content config was ignored if it was outside of content dir and has a parent dir with an underscore
#1247746f6b38 Thanks @ematipico! - Fixes an issue where the SSR build was emitting the dist/server/entry.mjs file with an incorrect import at the top of the file/
#12365a23985b Thanks @apatel369! - Fixes an issue where Astro.currentLocale was not correctly returning the locale for 404 and 500 pages.
#12067c48916c Thanks @stramel! - Adds experimental support for built-in SVG components.
This feature allows you to import SVG files directly into your Astro project as components. By default, Astro will inline the SVG content into your HTML output.
To enable this feature, set experimental.svg to true in your Astro config:
{
experimental: {
svg: true,
},
}
To use this feature, import an SVG file in your Astro project, passing any common SVG attributes to the imported component. Astro also provides a size attribute to set equal height and width properties:
---
import Logo from'./path/to/svg/file.svg';
---
<Logosize={24} />
For a complete overview, and to give feedback on this experimental API, see the Feature RFC.
#123298309c61 Thanks @florian-lefebvre! - Adds a new astro:routes:resolved hook to the Integration API. Also update the astro:build:done hook by deprecating routes and adding a new assets map.
When building an integration, you can now get access to routes inside the astro:routes:resolved hook:
constintegration= () => {
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': ({ routes }) => {
console.log(routes);
},
},
};
};
This hook runs before astro:config:done, and whenever a route changes in development.
The routes array from astro:build:done is now deprecated, and exposed properties are now available on astro:routes:resolved, except for distURL. For this, you can use the newly exposed assets map:
const integration = () => {
let routes
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': (params) => {
routes = params.routes
},
'astro:build:done': ({
routes
assets
}) => {
for (const route of routes) {
const distURL = assets.get(route.pattern)
if (distURL) {
Object.assign(route, { distURL })
}
}
console.log(routes)
}
}
}
}
#12377af867f3 Thanks @ascorbic! - Adds experimental support for automatic responsive images
This feature is experimental and may change in future versions. To enable it, set experimental.responsiveImages to true in your astro.config.mjs file.
astro.config.mjs
{
experimental: {
responsiveImages: true,
},
}
When this flag is enabled, you can pass a layout prop to any <Image /> or <Picture /> component to create a responsive image. When a layout is set, images have automatically generated srcset and sizes attributes based on the image’s dimensions and the layout type. Images with responsive and full-width layouts will have styles applied to ensure they resize according to their container.
---
import { Image, Picture } from'astro:assets';
import myImage from'../assets/my_image.png';
---
<Image
src={myImage}
alt="A description of my image."
layout="responsive"
width={800}
height={600}
/>
<Picture
src={myImage}
alt="A description of my image."
layout="full-width"
formats={['avif', 'webp', 'jpeg']}
/>
This <Image /> component will generate the following HTML output:
These are additional properties available to the <Image /> and <Picture /> components when responsive images are enabled:
layout: The layout type for the image. Can be responsive, fixed, full-width or none. Defaults to value of image.experimentalLayout.
fit: Defines how the image should be cropped if the aspect ratio is changed. Values match those of CSS object-fit. Defaults to cover, or the value of image.experimentalObjectFit if set.
position: Defines the position of the image crop if the aspect ratio is changed. Values match those of CSS object-position. Defaults to center, or the value of image.experimentalObjectPosition if set.
priority: If set, eagerly loads the image. Otherwise images will be lazy-loaded. Use this for your largest above-the-fold image. Defaults to false.
Default responsive image settings
You can enable responsive images for all <Image /> and <Picture /> components by setting image.experimentalLayout with a default value. This can be overridden by the layout prop on each component.
Example:
astro.config.mjs
{
image: {
// Used for all `<Image />` and `<Picture />` components unless overridden
experimentalLayout: 'responsive',
},
experimental: {
responsiveImages: true,
},
}
---
import { Image } from'astro:assets';
import myImage from'../assets/my_image.png';
---
<Imagesrc={myImage} alt="This will use responsive layout"width={800} height={600} />
<Imagesrc={myImage} alt="This will use full-width layout"layout="full-width" />
<Imagesrc={myImage} alt="This will disable responsive images"layout="none" />
For a complete overview, and to give feedback on this experimental API, see the Responsive Images RFC.
#124753f02d5f Thanks @ascorbic! - Changes the default content config location from src/content/config.* to src/content.config.*.
The previous location is still supported, and is required if the legacy.collections flag is enabled.
🐞 Patch Changes
#124244364bff Thanks @ematipico! - Fixes an issue where an incorrect usage of Astro actions was lost when porting the fix from v4 to v5
#12438c8f877c Thanks @ascorbic! - Fixes a bug where legacy content types were generated for content layer collections if they were in the content directory
#12436453ec6b Thanks @martrapp! - Fixes a potential null access in the clientside router
#123920462219 Thanks @apatel369! - Fixes an issue where scripts were not correctly injected during the build. The issue was triggered when there were injected routes with the same entrypoint and different pattern
#12373d10f918 Thanks @bholmesdev! - Changes the default behavior for Astro Action form requests to a standard POST submission.
In Astro 4.x, actions called from an HTML form would trigger a redirect with the result forwarded using cookies. This caused issues for large form errors and return values that exceeded the 4 KB limit of cookie-based storage.
Astro 5.0 now renders the result of an action as a POST result without any forwarding. This will introduce a “confirm form resubmission?” dialog when a user attempts to refresh the page, though it no longer imposes a 4 KB limit on action return value.
We recommend using a session storage provider as described in our Netlify Blob example. However, if you prefer the cookie forwarding behavior from 4.X and accept the 4 KB size limit, you can implement the pattern as shown in this sample snippet:
thrownewError('Internal: Referer unexpectedly missing from Action POST request.');
}
return context.redirect(referer);
}
// Redirect to the destination page on success
return context.redirect(context.originPathname);
}
returnnext();
});
🐞 Patch Changes
#12339bdb75a8 Thanks @ematipico! - Adds an error when Astro.rewrite() is used to rewrite an on-demand route with a static route when using the "server" output.
This is a forbidden rewrite because Astro can’t retrieve the emitted static route at runtime. This route is served by the hosting platform, and not Astro itself.
#12402823e73b Thanks @ematipico! - Fixes a case where Astro allowed to call an action without using Astro.callAction. This is now invalid, and Astro will show a proper error.
---
import { actions } from "astro:actions";
const result = actions.getUser({ userId: 123 });
const result = Astro.callAction(actions.getUser, { userId: 123 });
---
#124019cca108 Thanks @bholmesdev! - Fixes unexpected 200 status in dev server logs for action errors and redirects.
#12355c4726d7 Thanks @apatel369! - Improves error reporting for invalid frontmatter in MDX files during the astro build command. The error message now includes the file path where the frontmatter parsing failed.