0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00
astro/packages/astro/CHANGELOG.md
Houston (Bot) 218267c0b3
[ci] release (beta) (#12534)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-11-27 14:34:47 +00:00

731 KiB
Raw Blame History

astro

5.0.0-beta.12

Major Changes

Minor Changes

Patch Changes

  • Updated dependencies [827093e]:
    • @astrojs/telemetry@3.2.0-beta.0
    • @astrojs/markdown-remark@6.0.0-beta.3

5.0.0-beta.11

Minor Changes

  • #12510 14feaf3 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

5.0.0-beta.10

Patch Changes

5.0.0-beta.9

Minor Changes

  • #12067 c48916c 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';
    ---
    
    <Logo size={24} />
    

    For a complete overview, and to give feedback on this experimental API, see the Feature RFC.

  • #12329 8309c61 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:

    const integration = () => {
      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)
                }
            }
        }
    }
    
  • #12377 af867f3 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.

    {
       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:

    <img
      src="/_astro/my_image.hash3.webp"
      srcset="
        /_astro/my_image.hash1.webp  640w,
        /_astro/my_image.hash2.webp  750w,
        /_astro/my_image.hash3.webp  800w,
        /_astro/my_image.hash4.webp  828w,
        /_astro/my_image.hash5.webp 1080w,
        /_astro/my_image.hash6.webp 1280w,
        /_astro/my_image.hash7.webp 1600w
      "
      alt="A description of my image"
      sizes="(min-width: 800px) 800px, 100vw"
      loading="lazy"
      decoding="async"
      fetchpriority="auto"
      width="800"
      height="600"
      style="--w: 800; --h: 600; --fit: cover; --pos: center;"
      data-astro-image="responsive"
    />
    

    Responsive image properties

    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:

    {
        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';
    ---
    
    <Image src={myImage} alt="This will use responsive layout" width={800} height={600} />
    
    <Image src={myImage} alt="This will use full-width layout" layout="full-width" />
    
    <Image src={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.

  • #12475 3f02d5f 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

  • #12424 4364bff Thanks @ematipico! - Fixes an issue where an incorrect usage of Astro actions was lost when porting the fix from v4 to v5

  • #12438 c8f877c Thanks @ascorbic! - Fixes a bug where legacy content types were generated for content layer collections if they were in the content directory

5.0.0-beta.8

Minor Changes

  • #12373 d10f918 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.

    Customize form submission behavior

    If you prefer to address the "confirm form resubmission?" dialog on refresh, or to preserve action results across sessions, you can now customize action result handling from middleware.

    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:

    // src/middleware.ts
    import { defineMiddleware } from 'astro:middleware';
    import { getActionContext } from 'astro:actions';
    
    export const onRequest = defineMiddleware(async (context, next) => {
      // Skip requests for prerendered pages
      if (context.isPrerendered) return next();
    
      const { action, setActionResult, serializeActionResult } = getActionContext(context);
    
      // If an action result was forwarded as a cookie, set the result
      // to be accessible from `Astro.getActionResult()`
      const payload = context.cookies.get('ACTION_PAYLOAD');
      if (payload) {
        const { actionName, actionResult } = payload.json();
        setActionResult(actionName, actionResult);
        context.cookies.delete('ACTION_PAYLOAD');
        return next();
      }
    
      // If an action was called from an HTML form action,
      // call the action handler and redirect with the result as a cookie.
      if (action?.calledFrom === 'form') {
        const actionResult = await action.handler();
    
        context.cookies.set('ACTION_PAYLOAD', {
          actionName: action.name,
          actionResult: serializeActionResult(actionResult),
        });
    
        if (actionResult.error) {
          // Redirect back to the previous page on error
          const referer = context.request.headers.get('Referer');
          if (!referer) {
            throw new Error('Internal: Referer unexpectedly missing from Action POST request.');
          }
          return context.redirect(referer);
        }
        // Redirect to the destination page on success
        return context.redirect(context.originPathname);
      }
    
      return next();
    });
    

Patch Changes

  • #12339 bdb75a8 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.

5.0.0-beta.7

Minor Changes

5.0.0-beta.6

Major Changes

  • #12268 4e9a3ac 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.

  • #12231 90ae100 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.

Minor Changes

  • #12243 eb41d13 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.

  • #12150 93351bc 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:

    # Run the dev server connected to a "staging" API
    astro dev --mode staging
    
    # Build a site that connects to a "staging" API
    astro build --mode staging
    
    # Build a site that connects to a "production" API with additional debug information
    astro build --devOutput
    
    # Build a site that connects to a "testing" API
    astro build --mode testing
    

    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.

Patch Changes

  • #12302 7196c24 Thanks @ematipico! - Fixes an issue where the origin check middleware run for prendered pages

  • #12341 c1786d6 Thanks @ematipico! - Fixes and issue where Astro.currentLocale always returned the default locale when consumed inside a server island.

  • #12270 25192a0 Thanks @ematipico! - Fixes a bug where the params weren't correctly computed when rendering URLs with non-English characters

5.0.0-beta.5

Minor Changes

  • #12226 51d13e2 Thanks @ematipico! - The following renderer fields and integration fields now accept URL as a type:

    Renderers:

    • AstroRenderer.clientEntrpoint
    • AstroRenderer.serverEntrypoint

    Integrations:

    • InjectedRoute.entrypoint
    • AstroIntegrationMiddleware.entrypoint
    • DevToolbarAppEntry.entrypoint

Patch Changes

  • #12168 1cd3085 Thanks @ascorbic! - Allows "slug" as a field in content layer data

  • #12169 15fa9ba 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.

  • #12169 15fa9ba 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.

5.0.0-beta.4

Major Changes

  • #11979 423dfc1 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.

  • #12100 abf9a89 Thanks @astrobot-houston! - 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.

    ⚠️ BREAKING CHANGE FOR LEGACY CONTENT COLLECTIONS ⚠️

    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';
    
    export default defineConfig({
      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.

  • #12079 7febf1f 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;
    ---
    

Patch Changes

5.0.0-beta.3

Minor Changes

  • #12047 21b5e80 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.

    import { defineCollection } from "astro:content"
    import { file } from "astro/loaders"
    import { parse as parseToml } from "toml"
    
    const dogs = defineCollection({
      loader: file("src/data/dogs.toml", { parser: (text) => parseToml(text).dogs }),
      schema: /* ... */
    })
    
    // it also works with CSVs!
    import { parse as parseCsv } from "csv-parse/sync";
    
    const cats = defineCollection({
      loader: file("src/data/cats.csv", { parser: (text) => parseCsv(text, { columns: true, skipEmptyLines: true })})
    });
    

    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:

    const dogs = defineCollection({
      loader: file('src/data/pets.json', { parser: (text) => JSON.parse(text).dogs }),
    });
    const cats = defineCollection({
      loader: file('src/data/pets.json', { parser: (text) => JSON.parse(text).cats }),
    });
    

    And it continues to work with maps of id to data

    bubbles:
      breed: 'Goldfish'
      age: 2
    finn:
      breed: 'Betta'
      age: 1
    
    const fish = defineCollection({
      loader: file('src/data/fish.yaml'),
      schema: z.object({ breed: z.string(), age: z.number() }),
    });
    
  • #12071 61d248e 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

  • #11963 0a1036e 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:

    import { writeFileSync } from 'node:fs';
    
    const integration = {
      name: 'my-integration',
      hooks: {
        'astro:config:setup': ({ createCodegenDir }) => {
          const codegenDir = createCodegenDir();
          writeFileSync(new URL('cache.json', codegenDir), '{}', 'utf-8');
        },
      },
    };
    
  • #12081 8679954 Thanks @florian-lefebvre! - Removes the experimental contentCollectionsCache introduced in 3.5.0.

    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

  • #12073 acf264d Thanks @bluwy! - Replaces ora with yocto-spinner

  • #12075 a19530e Thanks @bluwy! - Parses frontmatter ourselves

  • #12070 9693ad4 Thanks @ematipico! - Fixes an issue where the check origin middleware was incorrectly injected when the build output was "static"

  • Updated dependencies [a19530e]:

    • @astrojs/markdown-remark@6.0.0-beta.2

5.0.0-beta.2

Patch Changes

  • #12035 325a57c Thanks @ascorbic! - Correctly parse values returned from inline loader

  • #12022 ddc3a08 Thanks @Princesseuh! - Properly handle including trailing slash on the image endpoint route based on the trailingSlash config

  • #12016 837ee3a Thanks @matthewp! - Fixes actions with large amount of validation errors

  • #12030 10a756a 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.

5.0.0-beta.1

Major Changes

  • #12008 5608338 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.

    To learn how to upgrade, check out the Astro v5.0 upgrade guide in our beta docs site.

Patch Changes

  • Updated dependencies [5608338]:
    • @astrojs/markdown-remark@6.0.0-beta.1

5.0.0-alpha.9

Patch Changes

5.0.0-alpha.8

Major Changes

  • #11982 d84e444 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.

  • #11987 bf90a53 Thanks @florian-lefebvre! - The locals object can no longer be overridden

    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,
    });
    

Minor Changes

  • #11980 a604a0c Thanks @matthewp! - ViewTransitions component renamed to ClientRouter

    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.

Patch Changes

  • #11987 bf90a53 Thanks @florian-lefebvre! - render() signature now takes renderOptions as 2nd argument

    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.
  • #11991 d7a396c Thanks @matthewp! - Update error link to on-demand rendering guide

5.0.0-alpha.7

Major Changes

  • #11864 ee38b3a 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) {
    
    }
    
  • #11908 518433e 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',
        },
      },
    });
    
  • #11806 f7f2338 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.

  • #11864 ee38b3a 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) {
    
    }
    
  • #11864 ee38b3a 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
    +    }
    +  }
    }
    

Minor Changes

  • #11806 f7f2338 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.

  • #11955 d813262 Thanks @matthewp! - Server Islands introduced behind an experimental flag in v4.12.0 is no longer experimental and is available for general use.

    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.

    ---
    import Avatar from '../components/Avatar.astro';
    import GenericUser from '../components/GenericUser.astro';
    ---
    
    <header>
      <h1>Page Title</h1>
      <div class="header-right">
        <Avatar server:defer>
          <GenericUser slot="fallback" />
        </Avatar>
      </div>
    </header>
    

    If you were previously using this feature, please remove the experimental flag from your Astro config:

    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      experimental {
    -    serverIslands: true,
      },
    });
    

    If you have been waiting for stabilization before using server islands, you can now do so.

    Please see the server island documentation for more about this feature.

  • #11806 f7f2338 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.

  • #11925 74722cb Thanks @florian-lefebvre! - Updates astro/config import to reference astro/client types

    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.

Patch Changes

5.0.0-alpha.6

Major Changes

  • #11941 b6a5f39 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.

Minor Changes

  • #11941 b6a5f39 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.

    {
      'astro:config:done': ({ setAdapter, config }) => {
        setAdapter({
          name: 'my-adapter',
          adapterFeatures: {
            buildOutput: 'server',
          },
        });
      },
    }
    

    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.

  • #11941 b6a5f39 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).

Patch Changes

  • #11960 4410130 Thanks @ascorbic! - Fixes an issue where the refresh context data was not passed correctly to content layer loaders

  • #11952 50a0146 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.

    const probes = defineCollection({
      // Load all markdown files in the space-probes directory, except for those that start with "voyager-"
      loader: glob({ pattern: ['*.md', '!voyager-*'], base: 'src/data/space-probes' }),
      schema: z.object({
        name: z.string(),
        type: z.enum(['Space Probe', 'Mars Rover', 'Comet Lander']),
        launch_date: z.date(),
        status: z.enum(['Active', 'Inactive', 'Decommissioned']),
        destination: z.string(),
        operator: z.string(),
        notable_discoveries: z.array(z.string()),
      }),
    });
    
  • #11968 86ad1fd Thanks @NikolaRHristov! - Fixes a typo in the server island JSDoc

  • #11983 633eeaa Thanks @uwej711! - Remove dependency on path-to-regexp

5.0.0-alpha.5

Major Changes

  • #11916 46ea29f 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.

Minor Changes

  • #11875 a8a3d2c 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
    
    export const prerender = true;
    ---
    
    // src/middleware.js
    
    export const onRequest = (ctx, next) => {
      console.log(ctx.isPrerendered); // it will log true
      return next();
    };
    

Patch Changes

  • #11927 5b4e3ab Thanks @florian-lefebvre! - Updates the env configuration reference docs to include a full API reference for envField.

  • #11943 fa4671c Thanks @sarah11918! - Updates error messages that assume content collections are located in src/content/ with more generic language

5.0.0-alpha.4

Major Changes

  • #11859 3804711 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"]
    }
    

Minor Changes

  • #11911 c3dce83 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';
    
    const blog = defineCollection({
      // The ID is a slug generated from the path of the file relative to `base`
      loader: glob({ pattern: '**/*.md', base: './src/data/blog' }),
      schema: z.object({
        title: z.string(),
        description: z.string(),
        publishDate: z.coerce.date(),
      }),
    });
    
    export const collections = { blog };
    

    You can then query using the existing content collections functions, and use a simplified render() function to display your content:

    ---
    import { getEntry, render } from 'astro:content';
    
    const post = await getEntry('blog', Astro.params.slug);
    
    const { Content } = await render(entry);
    ---
    
    <Content />
    

    Creating a loader

    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:

    // src/content/config.ts
    const countries = defineCollection({
      loader: async () => {
        const response = await fetch('https://restcountries.com/v3.1/all');
        const data = await response.json();
        // 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...
    });
    
    export const collections = { 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:

    // src/content/config.ts
    import { defineCollection } from 'astro:content';
    import { feedLoader } from '@ascorbic/feed-loader';
    
    const podcasts = defineCollection({
      loader: feedLoader({
        url: 'https://feeds.99percentinvisible.org/99percentinvisible',
      }),
    });
    
    export const collections = { podcasts };
    

    To learn more, see the Content Layer RFC.

Patch Changes

  • #11902 d63bc50 Thanks @ascorbic! - Fixes case where content layer did not update during clean dev builds on Linux and Windows

  • #11914 b5d827b 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.

5.0.0-alpha.3

Major Changes

  • #11861 3ab3b4e 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:

    • vfile.data.__astroHeadings -> vfile.data.astro.headings
    • vfile.data.imagePaths -> vfile.data.astro.imagePaths

    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.

  • #11825 560ef15 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.

  • #11819 2bdde80 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.

Patch Changes

  • #11878 334948c 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.

     {
        name: 'my-integration',
        hooks: {
            'astro:server:setup': async ({ server, refreshContent }) => {
                server.middlewares.use('/_refresh', async (req, res) => {
                    if(req.method !== 'POST') {
                      res.statusCode = 405
                      res.end('Method Not Allowed');
                      return
                    }
                    let body = '';
                    req.on('data', chunk => {
                        body += chunk.toString();
                    });
                    req.on('end', async () => {
                        try {
                            const webhookBody = JSON.parse(body);
                            await refreshContent({
                              context: { webhookBody },
                              loaders: ['my-loader']
                            });
                            res.writeHead(200, { 'Content-Type': 'application/json' });
                            res.end(JSON.stringify({ message: 'Content refreshed successfully' }));
                        } catch (error) {
                            res.writeHead(500, { 'Content-Type': 'application/json' });
                            res.end(JSON.stringify({ error: 'Failed to refresh content: ' + error.message }));
                        }
                    });
                });
            }
        }
    }
    
  • Updated dependencies [3ab3b4e, 560ef15, 3ab3b4e]:

    • @astrojs/markdown-remark@6.0.0-alpha.1

5.0.0-alpha.2

Major Changes

  • #11826 7315050 Thanks @matthewp! - Deprecate Astro.glob

    The Astro.glob function has been deprecated in favor of Content Collections and import.meta.glob.

    Also consider using glob packages from npm, like fast-glob, especially if statically generating your site, as it is faster for most use-cases.

    The easiest path is to migrate to import.meta.glob like so:

    - const posts = Astro.glob('./posts/*.md');
    + const posts = Object.values(import.meta.glob('./posts/*.md', { eager: true }));
    
  • #11827 a83e362 Thanks @matthewp! - Prevent usage of astro:content in the client

    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.

  • #11253 4e5cc5a 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>
    

Minor Changes

  • #11698 05139ef 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
    const route = Astro.routePattern;
    console.log(route); // it will log "blog/[slug]"
    ---
    
    // src/pages/index.js
    
    export const GET = (ctx) => {
      console.log(ctx.routePattern); // it will log src/pages/index.js
      return new Response.json({ loreum: 'ipsum' });
    };
    

Patch Changes

  • #11791 9393243 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.

5.0.0-alpha.1

Major Changes

  • #11798 e9e2139 Thanks @matthewp! - Unflag globalRoutePriority

    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.

  • #11679 ea71b90 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.

    import { defineConfig, envField } from 'astro/config';
    
    export default defineConfig({
      env: {
        schema: {
          API_URL: envField.string({ context: 'client', access: 'public', optional: true }),
          PORT: envField.number({ context: 'server', access: 'public', default: 4321 }),
          API_SECRET: envField.string({ context: 'server', access: 'secret' }),
        },
      },
    });
    

    You can import and use your defined variables from the appropriate /client or /server module:

    ---
    import { API_URL } from 'astro:env/client';
    import { API_SECRET_TOKEN } from 'astro:env/server';
    
    const data = await fetch(`${API_URL}/users`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${API_SECRET_TOKEN}`,
      },
    });
    ---
    
    <script>
      import { API_URL } from 'astro:env/client';
    
      fetch(`${API_URL}/ping`);
    </script>
    
  • #11788 7c0ccfc 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
    +  }
    })
    
  • #11741 6617491 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.

  • #11782 9a2aaa0 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} />
    
  • #11770 cfa6a47 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";
    import { defineConfig } from "astro/config";
    
    export default defineConfig({
    -  image: {
    -    service: squooshImageService()
    -  }
    });
    

    If you are using this service, and cannot migrate to the base Sharp image service, a third-party extraction of the previous service is available here: https://github.com/Princesseuh/astro-image-service-squoosh

5.0.0-alpha.0

Major Changes

  • #10742 b6fbdaa Thanks @ematipico! - The lowest version of Node supported by Astro is now Node v18.17.1 and higher.

  • #11715 d74617c 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.

  • #11660 e90f559 Thanks @bluwy! - Fixes attribute rendering for non-boolean HTML attributes with boolean values to match proper attribute handling in browsers.

    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 -->
    <p allowfullscreen={true}></p>
    <p allowfullscreen={false}></p>
    
    <!-- `inherit` is *not* a boolean attribute -->
    <p inherit={true}></p>
    <p inherit={false}></p>
    
    <!-- `data-*` attributes are not boolean attributes -->
    <p data-light={true}></p>
    <p data-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'
    
  • #11714 8a53517 Thanks @matthewp! - Remove support for functionPerRoute

    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

4.16.16

Patch Changes

4.16.15

Patch Changes

4.16.14

Patch Changes

  • #12480 c3b7e7c Thanks @matthewp! - Removes the default throw behavior in astro:env

  • #12444 28dd3ce Thanks @ematipico! - Fixes an issue where a server island hydration script might fail case the island ID misses from the DOM.

  • #12476 80a9a52 Thanks @florian-lefebvre! - Fixes a case where the Content Layer glob() loader would not update when renaming or deleting an entry

  • #12418 25baa4e Thanks @oliverlynch! - Fix cached image redownloading if it is the first asset

  • #12477 46f6b38 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/

  • #12365 a23985b Thanks @apatel369! - Fixes an issue where Astro.currentLocale was not correctly returning the locale for 404 and 500 pages.

4.16.13

Patch Changes

  • #12436 453ec6b Thanks @martrapp! - Fixes a potential null access in the clientside router

  • #12392 0462219 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

4.16.12

Patch Changes

  • #12420 acac0af Thanks @ematipico! - Fixes an issue where the dev server returns a 404 status code when a user middleware returns a valid Response.

4.16.11

Patch Changes

  • #12305 f5f7109 Thanks @florian-lefebvre! - Fixes a case where the error overlay would not escape the message

  • #12402 823e73b 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 });
    ---
    
  • #12401 9cca108 Thanks @bholmesdev! - Fixes unexpected 200 status in dev server logs for action errors and redirects.

4.16.10

Patch Changes

  • #12311 bf2723e Thanks @dinesh-58! - Adds checked to the list of boolean attributes.

  • #12363 222f718 Thanks @Fryuni! - Fixes code generated by astro add command when adding a version of an integration other than the default latest.

  • #12368 493fe43 Thanks @bluwy! - Improves error logs when executing commands

  • #12355 c4726d7 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.

4.16.9

Patch Changes

4.16.8

Patch Changes

  • #12338 9ca89b3 Thanks @situ2001! - Resets NODE_ENV to ensure install command run in dev mode

  • #12286 9d6bcdb Thanks @florian-lefebvre! - Fixes a case where a warning for experimental astro:env support would be shown when using an adapter but not actually using astro:env

  • #12342 ffc836b Thanks @liruifengv! - Fixes a typo in the command name of the CLI

  • #12301 0cfc69d Thanks @apatel369! - Fixes an issue with action handler context by passing the correct context (ActionAPIContext).

  • #12312 5642ef9 Thanks @koyopro! - Fixes an issue where using getViteConfig() returns incorrect and duplicate configuration

  • #12245 1d4f6a4 Thanks @bmenant! - Add components property to MDXInstance type definition (RenderResult and module import)

  • #12340 94eaeea Thanks @ematipico! - Fixes an issue where Astro actions didn't work when base was different from /

4.16.7

Patch Changes

  • #12263 e9e8080 Thanks @Fryuni! - Fixes conflict between server islands and on-demand dynamic routes in the form of /[...rest] or /[paramA]/[paramB].

  • #12279 b781f88 Thanks @jsparkdev! - Update wrong error message

  • #12273 c2ee963 Thanks @ascorbic! - Fixes an issue with some package managers where sites would not build if TypeScript was not installed.

  • #12235 a75bc5e Thanks @ematipico! - Fixes a bug where Astro Actions couldn't redirect to the correct pathname when there was a rewrite involved.

  • #11839 ff522b9 Thanks @icaliman! - Fixes error when returning a top-level null from an Astro file frontmatter

  • #12272 388d237 Thanks @ascorbic! - Correctly handles local images when using a base path in SSR

4.16.6

Patch Changes

  • #11823 a3d30a6 Thanks @DerTimonius! - fix: improve error message when inferSize is used in local images with the Image component

  • #12227 8b1a641 Thanks @florian-lefebvre! - Fixes a case where environment variables would not be refreshed when using astro:env

  • #12239 2b6daa5 Thanks @ematipico! - BREAKING CHANGE to the experimental Container API only

    Changes the default page rendering behavior of Astro components in containers, and adds a new option partial: false to render full Astro pages as before.

    Previously, the Container API was rendering all Astro components as if they were full Astro pages containing <!DOCTYPE html> by default. This was not intended, and now by default, all components will render as page partials: only the contents of the components without a page shell.

    To render the component as a full-fledged Astro page, pass a new option called partial: false to renderToString() and renderToResponse():

    import { experimental_AstroContainer as AstroContainer } from 'astro/container';
    import Card from '../src/components/Card.astro';
    
    const container = AstroContainer.create();
    
    await container.renderToString(Card); // the string will not contain `<!DOCTYPE html>`
    await container.renderToString(Card, { partial: false }); // the string will contain `<!DOCTYPE html>`
    

4.16.5

Patch Changes

  • #12232 ff68ba5 Thanks @martrapp! - Fixes an issue with cssesc in dev mode when setting vite.ssr.noExternal: true

4.16.4

Patch Changes

  • #12223 79ffa5d Thanks @ArmandPhilippot! - Fixes a false positive reported by the dev toolbar Audit app where a label was considered missing when associated with a button

    The button element can be used with a label (e.g. to create a switch) and should not be reported as an accessibility issue when used as a child of a label.

  • #12199 c351352 Thanks @ematipico! - Fixes a regression in the computation of Astro.currentLocale

  • #12222 fb55695 Thanks @ematipico! - Fixes an issue where the edge middleware couldn't correctly compute the client IP address when calling ctx.clientAddress()

4.16.3

Patch Changes

  • #12220 b049359 Thanks @bluwy! - Fixes accidental internal setOnSetGetEnv parameter rename that caused runtime errors

  • #12197 2aa2dfd Thanks @ematipico! - Fix a regression where a port was incorrectly added to the Astro.url

4.16.2

Patch Changes

4.16.1

Patch Changes

  • #12177 a4ffbfa Thanks @matthewp! - Ensure we target scripts for execution in the router

    Using document.scripts is unsafe because if the application has a name="scripts" this will shadow the built-in document.scripts. Fix is to use getElementsByTagName to ensure we're only grabbing real scripts.

  • #12173 2d10de5 Thanks @ematipico! - Fixes a bug where Astro Actions couldn't redirect to the correct pathname when there was a rewrite involved.

4.16.0

Minor Changes

  • #12039 710a1a1 Thanks @ematipico! - Adds a markdown.shikiConfig.langAlias option that allows aliasing a non-supported code language to a known language. This is useful when the language of your code samples is not a built-in Shiki language, but you want your Markdown source to contain an accurate language while also displaying syntax highlighting.

    The following example configures Shiki to highlight cjs code blocks using the javascript syntax highlighter:

    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      markdown: {
        shikiConfig: {
          langAlias: {
            cjs: 'javascript',
          },
        },
      },
    });
    

    Then in your Markdown, you can use the alias as the language for a code block for syntax highlighting:

    ```cjs
    'use strict';
    
    function commonJs() {
      return 'I am a commonjs file';
    }
    ```
    
  • #11984 3ac2263 Thanks @chaegumi! - Adds a new build.concurreny configuration option to specify the number of pages to build in parallel

    In most cases, you should not change the default value of 1.

    Use this option only when other attempts to reduce the overall rendering time (e.g. batch or cache long running tasks like fetch calls or data access) are not possible or are insufficient.

    Use this option only if the refactors are not possible. If the number is set too high, the page rendering may slow down due to insufficient memory resources and because JS is single-threaded.

    Warning

    This feature is stable and is not considered experimental. However, this feature is only intended to address difficult performance issues, and breaking changes may occur in a minor release to keep this option as performant as possible.

    // astro.config.mjs
    import { defineConfig } from 'astro';
    
    export default defineConfig({
      build: {
        concurrency: 2,
      },
    });
    

Patch Changes

  • #12160 c6fd1df Thanks @louisescher! - Fixes a bug where astro.config.mts and astro.config.cts weren't reloading the dev server upon modifications.

  • #12130 e96bcae Thanks @thehansys! - Fixes a bug in the parsing of x-forwarded-\* Request headers, where multiple values assigned to those headers were not correctly parsed.

    Now, headers like x-forwarded-proto: https,http are correctly parsed.

  • #12147 9db755a Thanks @ascorbic! - Skips setting statusMessage header for HTTP/2 response

    HTTP/2 doesn't support status message, so setting this was logging a warning.

  • #12151 bb6d37f Thanks @ematipico! - Fixes an issue where Astro.currentLocale wasn't incorrectly computed when the defaultLocale belonged to a custom locale path.

  • Updated dependencies [710a1a1]:

    • @astrojs/markdown-remark@5.3.0

4.15.12

Patch Changes

4.15.11

Patch Changes

  • #12097 11d447f Thanks @ascorbic! - Fixes error where references in content layer schemas sometimes incorrectly report as missing

  • #12108 918953b Thanks @lameuler! - Fixes a bug where data URL images were not correctly handled. The bug resulted in an ENAMETOOLONG error.

  • #12105 42037f3 Thanks @ascorbic! - Returns custom statusText that has been set in a Response

  • #12109 ea22558 Thanks @ematipico! - Fixes a regression that was introduced by an internal refactor of how the middleware is loaded by the Astro application. The regression was introduced by #11550.

    When the edge middleware feature is opted in, Astro removes the middleware function from the SSR manifest, and this wasn't taken into account during the refactor.

  • #12106 d3a74da Thanks @ascorbic! - Handles case where an immutable Response object is returned from an endpoint

  • #12090 d49a537 Thanks @markjaquith! - Server islands: changes the server island HTML placeholder comment so that it is much less likely to get removed by HTML minifiers.

4.15.10

Patch Changes

4.15.9

Patch Changes

  • #12034 5b3ddfa Thanks @ematipico! - Fixes an issue where the middleware wasn't called when a project uses 404.astro.

  • #12042 243ecb6 Thanks @ematipico! - Fixes a problem in the Container API, where a polyfill wasn't correctly applied. This caused an issue in some environments where crypto isn't supported.

  • #12038 26ea5e8 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.

4.15.8

Patch Changes

4.15.7

Patch Changes

4.15.6

Patch Changes

  • #11993 ffba5d7 Thanks @matthewp! - Fix getStaticPaths regression

    This reverts a previous change meant to remove a dependency, to fix a regression with multiple nested spread routes.

  • #11964 06eff60 Thanks @TheOtterlord! - Add wayland (wl-copy) support to astro info

4.15.5

Patch Changes

  • #11939 7b09c62 Thanks @bholmesdev! - Adds support for Zod discriminated unions on Action form inputs. This allows forms with different inputs to be submitted to the same action, using a given input to decide which object should be used for validation.

    This example accepts either a create or update form submission, and uses the type field to determine which object to validate against.

    import { defineAction } from 'astro:actions';
    import { z } from 'astro:schema';
    
    export const server = {
      changeUser: defineAction({
        accept: 'form',
        input: z.discriminatedUnion('type', [
          z.object({
            type: z.literal('create'),
            name: z.string(),
            email: z.string().email(),
          }),
          z.object({
            type: z.literal('update'),
            id: z.number(),
            name: z.string(),
            email: z.string().email(),
          }),
        ]),
        async handler(input) {
          if (input.type === 'create') {
            // input is { type: 'create', name: string, email: string }
          } else {
            // input is { type: 'update', id: number, name: string, email: string }
          }
        },
      }),
    };
    

    The corresponding create and update forms may look like this:

    ---
    import { actions } from 'astro:actions';
    ---
    
    <!--Create-->
    <form action={actions.changeUser} method="POST">
      <input type="hidden" name="type" value="create" />
      <input type="text" name="name" required />
      <input type="email" name="email" required />
      <button type="submit">Create User</button>
    </form>
    
    <!--Update-->
    <form action={actions.changeUser} method="POST">
      <input type="hidden" name="type" value="update" />
      <input type="hidden" name="id" value="user-123" />
      <input type="text" name="name" required />
      <input type="email" name="email" required />
      <button type="submit">Update User</button>
    </form>
    
  • #11968 86ad1fd Thanks @NikolaRHristov! - Fixes a typo in the server island JSDoc

  • #11983 633eeaa Thanks @uwej711! - Remove dependency on path-to-regexp

4.15.4

Patch Changes

  • #11879 bd1d4aa Thanks @matthewp! - Allow passing a cryptography key via ASTRO_KEY

    For Server islands Astro creates a cryptography key in order to hash props for the islands, preventing accidental leakage of secrets.

    If you deploy to an environment with rolling updates then there could be multiple instances of your app with different keys, causing potential key mismatches.

    To fix this you can now pass the ASTRO_KEY environment variable to your build in order to reuse the same key.

    To generate a key use:

    astro create-key
    

    This will print out an environment variable to set like:

    ASTRO_KEY=PIAuyPNn2aKU/bviapEuc/nVzdzZPizKNo3OqF/5PmQ=
    
  • #11935 c58193a Thanks @Princesseuh! - Fixes astro add not using the proper export point when adding certain adapters

4.15.3

Patch Changes

  • #11902 d63bc50 Thanks @ascorbic! - Fixes case where content layer did not update during clean dev builds on Linux and Windows

  • #11886 7ff7134 Thanks @matthewp! - Fixes a missing error message when actions throws during astro sync

  • #11904 ca54e3f Thanks @wtchnm! - perf(assets): avoid downloading original image when using cache

4.15.2

Patch Changes

  • #11870 8e5257a Thanks @ArmandPhilippot! - Fixes typo in documenting the fallbackType property in i18n routing

  • #11884 e450704 Thanks @ascorbic! - Correctly handles content layer data where the transformed value does not match the input schema

  • #11900 80b4a18 Thanks @delucis! - Fixes the user-facing type of the new i18n.routing.fallbackType option to be optional

4.15.1

Patch Changes

4.15.0

Minor Changes

  • #11729 1c54e63 Thanks @ematipico! - Adds a new variant sync for the astro:config:setup hook's command property. This value is set when calling the command astro sync.

    If your integration previously relied on knowing how many variants existed for the command property, you must update your logic to account for this new option.

  • #11743 cce0894 Thanks @ph1p! - Adds a new, optional property timeout for the client:idle directive.

    This value allows you to specify a maximum time to wait, in milliseconds, before hydrating a UI framework component, even if the page is not yet done with its initial load. This means you can delay hydration for lower-priority UI elements with more control to ensure your element is interactive within a specified time frame.

    <ShowHideButton client:idle={{ timeout: 500 }} />
    
  • #11677 cb356a5 Thanks @ematipico! - Adds a new option fallbackType to i18n.routing configuration that allows you to control how fallback pages are handled.

    When i18n.fallback is configured, this new routing option controls whether to redirect to the fallback page, or to rewrite the fallback page's content in place.

    The "redirect" option is the default value and matches the current behavior of the existing fallback system.

    The option "rewrite" uses the new rewriting system to create fallback pages that render content on the original, requested URL without a browser refresh.

    For example, the following configuration will generate a page /fr/index.html that will contain the same HTML rendered by the page /en/index.html when src/pages/fr/index.astro does not exist.

    // astro.config.mjs
    export default defineConfig({
      i18n: {
        locals: ['en', 'fr'],
        defaultLocale: 'en',
        routing: {
          prefixDefaultLocale: true,
          fallbackType: 'rewrite',
        },
        fallback: {
          fr: 'en',
        },
      },
    });
    
  • #11708 62b0d20 Thanks @martrapp! - Adds a new object swapFunctions to expose the necessary utility functions on astro:transitions/client that allow you to build custom swap functions to be used with view transitions.

    The example below uses these functions to replace Astro's built-in default swap function with one that only swaps the <main> part of the page:

    <script>
      import { swapFunctions } from 'astro:transitions/client';
    
      document.addEventListener('astro:before-swap', (e) => { e.swap = () => swapMainOnly(e.newDocument) });
    
      function swapMainOnly(doc: Document) {
        swapFunctions.deselectScripts(doc);
        swapFunctions.swapRootAttributes(doc);
        swapFunctions.swapHeadElements(doc);
        const restoreFocusFunction = swapFunctions.saveFocus();
        const newMain = doc.querySelector('main');
        const oldMain = document.querySelector('main');
        if (newMain && oldMain) {
          swapFunctions.swapBodyElement(newMain, oldMain);
        } else {
          swapFunctions.swapBodyElement(doc.body, document.body);
        }
        restoreFocusFunction();
      };
    </script>
    

    See the view transitions guide for more information about hooking into the astro:before-swap lifecycle event and adding a custom swap implementation.

  • #11843 5b4070e Thanks @bholmesdev! - Exposes z from the new astro:schema module. This is the new recommended import source for all Zod utilities when using Astro Actions.

    Migration for Astro Actions users

    z will no longer be exposed from astro:actions. To use z in your actions, import it from astro:schema instead:

    import {
      defineAction,
    -  z,
    } from 'astro:actions';
    + import { z } from 'astro:schema';
    
  • #11843 5b4070e Thanks @bholmesdev! - The Astro Actions API introduced behind a flag in v4.8.0 is no longer experimental and is available for general use.

    Astro Actions allow you to define and call backend functions with type-safety, performing data fetching, JSON parsing, and input validation for you.

    Actions can be called from client-side components and HTML forms. This gives you to flexibility to build apps using any technology: React, Svelte, HTMX, or just plain Astro components. This example calls a newsletter action and renders the result using an Astro component:

    ---
    // src/pages/newsletter.astro
    import { actions } from 'astro:actions';
    const result = Astro.getActionResult(actions.newsletter);
    ---
    
    {result && !result.error && <p>Thanks for signing up!</p>}
    <form method="POST" action={actions.newsletter}>
      <input type="email" name="email" />
      <button>Sign up</button>
    </form>
    

    If you were previously using this feature, please remove the experimental flag from your Astro config:

    import { defineConfig } from 'astro'
    
    export default defineConfig({
    -  experimental: {
    -    actions: true,
    -  }
    })
    

    If you have been waiting for stabilization before using Actions, you can now do so.

    For more information and usage examples, see our brand new Actions guide.

Patch Changes

  • #11677 cb356a5 Thanks @ematipico! - Fixes a bug in the logic of Astro.rewrite() which led to the value for base, if configured, being automatically prepended to the rewrite URL passed. This was unintended behavior and has been corrected, and Astro now processes the URLs exactly as passed.

    If you use the rewrite() function on a project that has base configured, you must now prepend the base to your existing rewrite URL:

    // astro.config.mjs
    export default defineConfig({
      base: '/blog',
    });
    
    // src/middleware.js
    export function onRequest(ctx, next) {
    -  return ctx.rewrite("/about")
    +  return ctx.rewrite("/blog/about")
    }
    
  • #11862 0e35afe Thanks @ascorbic! - BREAKING CHANGE to experimental content layer loaders only!

    Passes AstroConfig instead of AstroSettings object to content layer loaders.

    This will not affect you unless you have created a loader that uses the settings object. If you have, you will need to update your loader to use the config object instead.

    export default function myLoader() {
      return {
        name: 'my-loader'
    -   async load({ settings }) {
    -     const base = settings.config.base;
    +   async load({ config }) {
    +     const base = config.base;
          // ...
        }
      }
    }
    
    

    Other properties of the settings object are private internals, and should not be accessed directly. If you think you need access to other properties, please open an issue to discuss your use case.

  • #11772 6272e6c Thanks @bluwy! - Uses magicast to update the config for astro add

  • #11845 440a4be Thanks @bluwy! - Replaces execa with tinyexec internally

  • #11858 8bab233 Thanks @ascorbic! - Correctly resolves content layer images when filePath is not set

4.14.6

Patch Changes

4.14.5

Patch Changes

  • #11809 62e97a2 Thanks @bholmesdev! - Fixes usage of .transform(), .refine(), .passthrough(), and other effects on Action form inputs.

  • #11812 260c4be Thanks @bholmesdev! - Exposes ActionAPIContext type from the astro:actions module.

  • #11813 3f7630a Thanks @bholmesdev! - Fixes unexpected undefined value when calling an action from the client without a return value.

4.14.4

Patch Changes

  • #11794 3691a62 Thanks @bholmesdev! - Fixes unexpected warning log when using Actions on "hybrid" rendered projects.

  • #11801 9f943c1 Thanks @delucis! - Fixes a bug where the filePath property was not available on content collection entries when using the content layer file() loader with a JSON file that contained an object instead of an array. This was breaking use of the image() schema utility among other things.

4.14.3

Patch Changes

4.14.2

Patch Changes

  • #11733 391324d Thanks @bluwy! - Reverts back to yargs-parser package for CLI argument parsing

4.14.1

Patch Changes

  • #11725 6c1560f Thanks @ascorbic! - Prevents content layer importing node builtins in runtime

  • #11692 35af73a Thanks @matthewp! - Prevent errant HTML from crashing server islands

    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.

  • #11727 3c2f93b Thanks @florian-lefebvre! - Fixes a type issue when using the Content Layer in dev

4.14.0

Minor Changes

  • #11657 a23c69d 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:

    // src/pages/blog/[slug].astro
    - export const prerender = import.meta.env.PRERENDER
    

    Instead, create an integration with the "astro:route:setup" hook and update the route's prerender option:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    import { loadEnv } from 'vite';
    
    export default defineConfig({
      integrations: [setPrerender()],
    });
    
    function setPrerender() {
      const { PRERENDER } = loadEnv(process.env.NODE_ENV, process.cwd(), '');
    
      return {
        name: 'set-prerender',
        hooks: {
          'astro:route:setup': ({ route }) => {
            if (route.component.endsWith('/blog/[slug].astro')) {
              route.prerender = PRERENDER;
            }
          },
        },
      };
    }
    
  • #11360 a79a8b0 Thanks @ascorbic! - Adds a new injectTypes() utility to the Integration API and refactors how type generation works

    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.

    // my-integration/index.js
    export default {
      name: 'my-integration',
      'astro:config:done': ({ injectTypes }) => {
        injectTypes({
          filename: 'types.d.ts',
          content: "declare module 'virtual:my-integration' {}",
        });
      },
    };
    

    Codegen has been refactored. Although src/env.d.ts will continue to work as is, we recommend you update it:

    - /// <reference types="astro/client" />
    + /// <reference path="../.astro/types.d.ts" />
    - /// <reference path="../.astro/env.d.ts" />
    - /// <reference path="../.astro/actions.d.ts" />
    
  • #11605 d3d99fb Thanks @jcayzac! - Adds a new property meta to Astro's built-in <Code /> component.

    This allows you to provide a value for Shiki's meta attribute to pass options to transformers.

    The following example passes an option to highlight lines 1 and 3 to Shiki's tranformerMetaHighlight:

    ---
    // src/components/Card.astro
    import { Code } from 'astro:components';
    import { transformerMetaHighlight } from '@shikijs/transformers';
    ---
    
    <Code code={code} lang="js" transformers={[transformerMetaHighlight()]} meta="{1,3}" />
    
  • #11360 a79a8b0 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';
    
    export default defineConfig({
      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.

    See the experimental content Intellisense docs for more information updates as this feature develops.

  • #11360 a79a8b0 Thanks @ascorbic! - Adds experimental support for the Content Layer API.

    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';
    
    export default defineConfig({
      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';
    
    const blog = defineCollection({
      // The ID is a slug generated from the path of the file relative to `base`
      loader: glob({ pattern: '**/*.md', base: './src/data/blog' }),
      schema: z.object({
        title: z.string(),
        description: z.string(),
        publishDate: z.coerce.date(),
      }),
    });
    
    export const collections = { blog };
    

    You can then query using the existing content collections functions, and enjoy a simplified render() function to display your content:

    ---
    import { getEntry, render } from 'astro:content';
    
    const post = await getEntry('blog', Astro.params.slug);
    
    const { Content } = await render(entry);
    ---
    
    <Content />
    

    Creating a loader

    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:

    // src/content/config.ts
    const countries = defineCollection({
      loader: async () => {
        const response = await fetch('https://restcountries.com/v3.1/all');
        const data = await response.json();
        // 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...
    });
    
    export const collections = { 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:

    // src/content/config.ts
    import { defineCollection } from 'astro:content';
    import { feedLoader } from '@ascorbic/feed-loader';
    
    const podcasts = defineCollection({
      loader: feedLoader({
        url: 'https://feeds.99percentinvisible.org/99percentinvisible',
      }),
    });
    
    export const collections = { podcasts };
    

    Learn more

    To find out more about using the Content Layer API, check out the Content Layer RFC and share your feedback.

Patch Changes

4.13.4

Patch Changes

  • #11678 34da907 Thanks @ematipico! - Fixes a case where omitting a semicolon and line ending with carriage return - CRLF - in the prerender option could throw an error.

  • #11535 932bd2e Thanks @matthewp! - Encrypt server island props

    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.

    See the RFC for an explanation: https://github.com/withastro/roadmap/blob/server-islands/proposals/server-islands.md#props-serialization

  • #11655 dc0a297 Thanks @billy-le! - Fixes Astro Actions input validation when using default values with a form input.

  • #11689 c7bda4c 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.

4.13.3

Patch Changes

  • #11653 32be549 Thanks @florian-lefebvre! - Updates astro:env docs to reflect current developments and usage guidance

  • #11658 13b912a Thanks @bholmesdev! - Fixes orThrow() type when calling an Action without an input validator.

  • #11603 f31d466 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:

    <form method="POST" action={'/success' + actions.signup}></form>
    
    • On success, Astro will redirect to /success.
    • 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.

4.13.2

Patch Changes

  • #11648 589d351 Thanks @bholmesdev! - Fixes unexpected error when refreshing a POST request from a form using Actions.

  • #11600 09ec2ca Thanks @ArmandPhilippot! - Deprecates getEntryBySlug and getDataEntryById functions exported by astro:content in favor of getEntry.

  • #11593 81d7150 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.

  • #11617 196092a Thanks @abubakriz! - Fix toolbar audit incorrectly flagging images as above the fold.

  • #11634 2716f52 Thanks @bholmesdev! - Fixes internal server error when calling an Astro Action without arguments on Vercel.

  • #11628 9aaf58c Thanks @madbook! - Ensures consistent CSS chunk hashes across different environments

4.13.1

Patch Changes

  • #11584 a65ffe3 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.

    ---
    import { actions } from 'astro:actions';
    
    const result = await Astro.callAction(actions.searchPosts, {
      searchTerm: Astro.url.searchParams.get('search'),
    });
    ---
    
    {
      result.data &&
        {
          /* render the results */
        }
    }
    

    Migration

    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' });
    ---
    

    If you deploy with Cloudflare and added the nodejs_compat or nodejs_als flags for Actions, we recommend removing these:

    compatibility_flags = [
    - "nodejs_compat",
    - "nodejs_als"
    ]
    

    You can also remove node:async_hooks from the vite.ssr.external option in your astro.config file:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
    - vite: {
    -   ssr: {
    -     external: ["node:async_hooks"]
    -   }
    - }
    })
    

4.13.0

Minor Changes

  • #11507 a62345f 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.

  • #11379 e5e2d3e 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:

    {
      "$schema": "../../../.astro/collections/authors.schema.json",
      "name": "Armand",
      "skills": ["Astro", "Starlight"]
    }
    

    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.

    Please see the content collections guide for more about this feature.

  • #11542 45ad326 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
    export function GET(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
    export function onRequest(context, next) {
      if (!context.cookies.get('allowed')) {
        return next('/'); // new signature
      }
      return next();
    }
    

    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.

    Please see the routing guide in docs for more about using this feature.

4.12.3

Patch Changes

  • #11509 dfbca06 Thanks @bluwy! - Excludes hoisted scripts and styles from Astro components imported with ?url or ?raw

  • #11561 904f1e5 Thanks @ArmandPhilippot! - Uses the correct pageSize default in page.size JSDoc comment

  • #11571 1c3265a 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
    const newLikes = await actions.like();
    // After
    const newLikes = await actions.like.orThrow();
    

    Migration

    To migrate your existing action calls:

    • Remove .safe from existing safe action calls
    • Add .orThrow to existing unsafe action calls
  • #11546 7f26de9 Thanks @ArmandPhilippot! - Remove "SSR Only" mention in Astro.redirect inline documentation and update reference link.

  • #11525 8068131 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.

  • #11574 e3f29d4 Thanks @Princesseuh! - Fixes line with the error not being properly highlighted in the error overlay

  • #11570 84189b6 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';
    ---
    
    <form action={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:

    ---
    import { actions } from 'astro:actions';
    
    const confirmationUrl = new URL('/confirmation', Astro.url);
    confirmationUrl.search = actions.queryString;
    ---
    
    <form method="POST" action={confirmationUrl.pathname}>
      <button>Submit</button>
    </form>
    

    Migration

    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:

    ---
    import {
      actions,
    - getActionProps,
    } from 'astro:actions';
    ---
    
    + <form method="POST" action={actions.logOut}>
    - <form method="POST">
    - <input {...getActionProps(actions.logOut)} />
      <button>Log Out</button>
    </form>
    
  • #11559 1953dbb Thanks @bryanwood! - Allows actions to return falsy values without an error

  • #11553 02c85b5 Thanks @ematipico! - Fixes an issue in content collection caching, where two documents with the same contents were generating an error during the build.

  • #11548 602c5bf Thanks @TheOtterlord! - Fixes astro add for packages with only prerelease versions

  • #11566 0dcef3a Thanks @Princesseuh! - Fixes DomException errors not being handled properly

  • #11529 504c383 Thanks @matthewp! - Fix server islands with trailingSlash: always

4.12.2

Patch Changes

  • #11505 8ff7658 Thanks @ematipico! - Enhances the dev server logging when rewrites occur during the lifecycle or rendering.

    The dev server will log the status code before and after a rewrite:

    08:16:48 [404] (rewrite) /foo/about 200ms
    08:22:13 [200] (rewrite) /about 23ms
    
  • #11506 026e8ba Thanks @sarah11918! - Fixes typo in documenting the slot="fallback" attribute for Server Islands experimental feature.

  • #11508 ca335e1 Thanks @cramforce! - Escapes HTML in serialized props

  • #11501 4db78ae Thanks @martrapp! - Adds the missing export for accessing the getFallback() function of the client site router.

4.12.1

Patch Changes

  • #11486 9c0c849 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:

    const container = await experimental_AstroContainer.create();
    container.addServerRenderer({ renderer });
    container.addClientRenderer({ name: '@astrojs/react', entrypoint: '@astrojs/react/client.js' });
    const response = await container.renderToResponse(Component);
    
  • #11500 4e142d3 Thanks @Princesseuh! - Fixes inferRemoteSize type not working

  • #11496 53ccd20 Thanks @alfawal! - Hide the dev toolbar on window.print() (CTRL + P)

4.12.0

Minor Changes

  • #11341 49b5145 Thanks @madcampos! - Adds support for Shiki's defaultColor option.

    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.

    import { defineConfig } from 'astro/config';
    export default defineConfig({
      markdown: {
        shikiConfig: {
          themes: {
            light: 'github-light',
            dark: 'github-dark',
          },
          defaultColor: false,
        },
      },
    });
    
    ---
    import { Code } from 'astro:components';
    ---
    
    <Code code={`const useMyColors = true`} lang="js" defaultColor={false} />
    
  • #11304 2e70741 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:

    // your-integration/types.ts
    declare global {
      namespace Astro {
        interface IntegrationHooks {
          'myLib:eventHappened': (your: string, parameters: number) => Promise<void>;
        }
      }
    }
    

    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:

    // your-integration/index.ts
    import './types.ts';
    
    export default (): AstroIntegration => {
      return {
        name: 'your-integration',
        hooks: {
          'astro:config:setup': async ({ config }) => {
            for (const integration of config.integrations) {
              await integration.hooks['myLib:eventHappened'].?('your values', 123);
            }
          },
        }
      }
    }
    

    Other integrations can also now declare your hooks:

    // other-integration/index.ts
    import 'your-integration/types.ts';
    
    export default (): AstroIntegration => {
      return {
        name: 'other-integration',
        hooks: {
          'myLib:eventHappened': async (your, values) => {
            // ...
          },
        },
      };
    };
    
  • #11305 d495df5 Thanks @matthewp! - Experimental Server Islands

    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:

    ---
    import Avatar from '../components/Avatar.astro';
    import GenericUser from '../components/GenericUser.astro';
    ---
    
    <header>
      <h1>Page Title</h1>
      <div class="header-right">
        <Avatar server:defer>
          <GenericUser slot="fallback" />
        </Avatar>
      </div>
    </header>
    

    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:

    import { defineConfig } from 'astro/config';
    import netlify from '@astrojs/netlify';
    
    export default defineConfig({
      output: 'hybrid',
      adapter: netlify(),
      experimental: {
        serverIslands: true,
      },
    });
    

    For more information, see the server islands documentation.

  • #11482 7c9ed71 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

  • #11098 36e30a3 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.

    ---
    import { inferRemoteSize, Image } from 'astro:assets';
    
    const imageUrl = 'https://...';
    const { width, height } = await inferRemoteSize(imageUrl);
    ---
    
    <Image src={imageUrl} width={width / 2} height={height} densities={[1.5, 2]} />
    
  • #11391 6f9b527 Thanks @ARipeAppleByYoursTruly! - Adds Shiki's defaultColor option to the <Code /> component, giving you more control in applying multiple themes

  • #11176 a751458 Thanks @tsawada! - Adds two new values to the pagination page prop: page.first and page.last for accessing the URLs of the first and last pages.

Patch Changes

  • #11477 7e9c4a1 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.

  • #11479 ca969d5 Thanks @florian-lefebvre! - Fixes a case where invalid astro:env variables at runtime would not throw correctly

  • #11489 061f1f4 Thanks @ematipico! - Move root inside the manifest and make serialisable

  • #11415 e9334d0 Thanks @florian-lefebvre! - Refactors how sync works and when it's called. Fixes an issue with astro:env types in dev not being generated

  • #11478 3161b67 Thanks @bluwy! - Supports importing Astro components with Vite queries, like ?url, ?raw, and ?direct

  • #11491 fe3afeb Thanks @matthewp! - Fix for Server Islands in Vercel adapter

    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.

  • #11483 34f9c25 Thanks @Princesseuh! - Fixes Astro not working on low versions of Node 18 and 20

  • Updated dependencies [49b5145]:

    • @astrojs/markdown-remark@5.2.0

4.11.6

Patch Changes

  • #11459 bc2e74d Thanks @mingjunlu! - Fixes false positive audit warnings on elements with the role "tabpanel".

  • #11472 cb4e6d0 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.

  • #11387 b498461 Thanks @bluwy! - Fixes prerendering not removing unused dynamic imported chunks

  • #11437 6ccb30e 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

  • #11439 08baf56 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.

    // example.ts
    import { actions, isInputError } from 'astro:actions';
    
    try {
      await actions.like(new FormData());
    } catch (error) {
      if (isInputError(error)) {
        console.log(error.fields);
      }
    }
    
  • #11452 0e66849 Thanks @FugiTech! - Fixes an issue where using .nullish() in a formdata Astro action would always parse as a string

  • #11438 619f07d Thanks @bholmesdev! - Exposes utility types from astro:actions for the defineAction handler (ActionHandler) and the ActionError code (ActionErrorCode).

  • #11456 17e048d Thanks @RickyC0626! - Fixes astro dev --open unexpected behavior that spawns a new tab every time a config file is saved

  • #11337 0a4b31f 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.

    // astro.config.mjs
    import { defineConfig, envField } from 'astro/config';
    
    export default defineConfig({
      experimental: {
        env: {
          schema: {
            // ...
          },
          validateSecrets: true,
        },
      },
    });
    
  • #11443 ea4bc04 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';
    
    export const server = {
      like: defineAction({
        handler: () => {
          /* ... */
          return { likes: 42 };
        },
      }),
    };
    

    In your client code, you can infer this handler return value with ActionReturnType:

    // client.ts
    import { actions, ActionReturnType } from 'astro:actions';
    
    type LikesResult = ActionReturnType<typeof actions.like>;
    // -> { likes: number }
    
  • #11436 7dca68f Thanks @bholmesdev! - Fixes astro:actions autocompletion for the defineAction accept property

  • #11455 645e128 Thanks @florian-lefebvre! - Improves astro:env invalid variables errors

4.11.5

Patch Changes

4.11.4

Patch Changes

  • #11362 93993b7 Thanks @ematipico! - Fixes an issue where creating manually the i18n middleware could break the logic of the functions of the virtual module astro:i18n

  • #11349 98d9ce4 Thanks @ematipico! - Fixes an issue where Astro didn't throw an error when Astro.rewrite was used without providing the experimental flag

  • #11352 a55ee02 Thanks @ematipico! - Fixes an issue where the rewrites didn't update the status code when using manual i18n routing.

  • #11388 3a223b4 Thanks @mingjunlu! - Adjusts the color of punctuations in error overlay.

  • #11369 e6de11f Thanks @bluwy! - Fixes attribute rendering for non-boolean attributes with boolean values

4.11.3

Patch Changes

  • #11347 33bdc54 Thanks @bluwy! - Fixes installed packages detection when running astro check

  • #11327 0df8142 Thanks @ematipico! - Fixes an issue with the container APIs where a runtime error was thrown during the build, when using pnpm as package manager.

4.11.2

Patch Changes

  • #11335 4c4741b Thanks @ematipico! - Reverts #11292, which caused a regression to the input type

  • #11326 41121fb Thanks @florian-lefebvre! - Fixes a case where running astro sync when using the experimental astro:env feature would fail if environment variables were missing

  • #11338 9752a0b Thanks @zaaakher! - Fixes svg icon margin in devtool tooltip title to look coherent in rtl and ltr layouts

  • #11331 f1b78a4 Thanks @bluwy! - Removes resolve package and simplify internal resolve check

  • #11339 8fdbf0e Thanks @matthewp! - Remove non-fatal errors from telemetry

    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.

4.11.1

Patch Changes

  • #11308 44c61dd 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.

  • #11302 0622567 Thanks @martrapp! - Fixes an issue with the view transition router when redirecting to an URL with different origin.

  • Updated dependencies [b6afe6a, 41064ce]:

    • @astrojs/markdown-remark@5.1.1
    • @astrojs/internal-helpers@0.4.1

4.11.0

Minor Changes

  • #11197 4b46bd9 Thanks @braebo! - Adds ShikiTransformer support to the <Code /> component with a new transformers prop.

    Note that transformers only applies classes and you must provide your own CSS rules to target the elements of your code block.

    ---
    import { transformerNotationFocus } from '@shikijs/transformers';
    import { Code } from 'astro:components';
    
    const code = `const foo = 'hello'
    const bar = ' world'
    console.log(foo + bar) // [!code focus]
    `;
    ---
    
    <Code {code} lang="js" transformers={[transformerNotationFocus()]} />
    
    <style is:global>
      pre.has-focused .line:not(.focused) {
        filter: blur(1px);
      }
    </style>
    
  • #11134 9042be0 Thanks @florian-lefebvre! - Improves the developer experience of the 500.astro file by passing it a new error prop.

    When an error is thrown, the special src/pages/500.astro page now automatically receives the error as a prop. This allows you to display more specific information about the error on a custom 500 page.

    ---
    // src/pages/500.astro
    interface Props {
      error: unknown;
    }
    
    const { error } = Astro.props;
    ---
    
    <div>{error instanceof Error ? error.message : 'Unknown error'}</div>
    

    If an error occurs rendering this page, your host's default 500 error page will be shown to your visitor in production, and Astro's default error overlay will be shown in development.

Patch Changes

  • #11280 fd3645f Thanks @ascorbic! - Fixes a bug that prevented cookies from being set when using experimental rewrites

  • #11275 bab700d Thanks @syhily! - Drop duplicated brackets in data collections schema generation.

  • #11272 ea987d7 Thanks @ematipico! - Fixes a case where rewriting / would cause an issue, when trailingSlash was set to "never".

  • #11272 ea987d7 Thanks @ematipico! - Reverts a logic where it wasn't possible to rewrite /404 in static mode. It's now possible again

  • #11264 5a9c9a6 Thanks @Fryuni! - Fixes type generation for empty content collections

  • #11279 9a08d74 Thanks @ascorbic! - Improves type-checking and error handling to catch case where an image import is passed directly to getImage()

  • #11292 7f8f347 Thanks @jdtjenkins! - Fixes a case where defineAction autocomplete for the accept prop would not show "form" as a possible value

  • #11273 cb4d078 Thanks @ascorbic! - Corrects an inconsistency in dev where middleware would run for prerendered 404 routes. Middleware is not run for prerendered 404 routes in production, so this was incorrect.

  • #11284 f4b029b Thanks @ascorbic! - Fixes an issue that would break Astro.request.url and Astro.request.headers in astro dev if HTTP/2 was enabled.

    HTTP/2 is now enabled by default in astro dev if https is configured in the Vite config.

4.10.3

Patch Changes

  • #11213 94ac7ef Thanks @florian-lefebvre! - Removes the PUBLIC_ prefix constraint for astro:env public variables

  • #11213 94ac7ef Thanks @florian-lefebvre! - BREAKING CHANGE to the experimental astro:env feature only

    Server secrets specified in the schema must now be imported from astro:env/server. Using getSecret() is no longer required to use these environment variables in your schema:

    - import { getSecret } from 'astro:env/server'
    - const API_SECRET = getSecret("API_SECRET")
    + import { API_SECRET } from 'astro:env/server'
    

    Note that using getSecret() with these keys is still possible, but no longer involves any special handling and the raw value will be returned, just like retrieving secrets not specified in your schema.

  • #11234 4385bf7 Thanks @ematipico! - Adds a new function called addServerRenderer to the Container API. Use this function to manually store renderers inside the instance of your container.

    This new function should be preferred when using the Container API in environments like on-demand pages:

    import type { APIRoute } from 'astro';
    import { experimental_AstroContainer } from 'astro/container';
    import reactRenderer from '@astrojs/react/server.js';
    import vueRenderer from '@astrojs/vue/server.js';
    import ReactComponent from '../components/button.jsx';
    import VueComponent from '../components/button.vue';
    
    // MDX runtime is contained inside the Astro core
    import mdxRenderer from 'astro/jsx/server.js';
    
    // In case you need to import a custom renderer
    import customRenderer from '../renderers/customRenderer.js';
    
    export const GET: APIRoute = async (ctx) => {
      const container = await experimental_AstroContainer.create();
      container.addServerRenderer({ renderer: reactRenderer });
      container.addServerRenderer({ renderer: vueRenderer });
      container.addServerRenderer({ renderer: customRenderer });
      // You can pass a custom name too
      container.addServerRenderer({
        name: 'customRenderer',
        renderer: customRenderer,
      });
      const vueComponent = await container.renderToString(VueComponent);
      return await container.renderToResponse(Component);
    };
    
  • #11249 de60c69 Thanks @markgaze! - Fixes a performance issue with JSON schema generation

  • #11242 e4fc2a0 Thanks @ematipico! - Fixes a case where the virtual module astro:container wasn't resolved

  • #11236 39bc3a5 Thanks @ascorbic! - Fixes a case where symlinked content collection directories were not correctly resolved

  • #11258 d996db6 Thanks @ascorbic! - Adds a new error RewriteWithBodyUsed that throws when Astro.rewrite is used after the request body has already been read.

  • #11243 ba2b14c Thanks @V3RON! - Fixes a prerendering issue for libraries in node_modules when a folder with an underscore is in the path.

  • #11244 d07d2f7 Thanks @ematipico! - Improves the developer experience of the custom 500.astro page in development mode.

    Before, in development, an error thrown during the rendering phase would display the default error overlay, even when users had the 500.astro page.

    Now, the development server will display the 500.astro and the original error is logged in the console.

  • #11240 2851b0a Thanks @ascorbic! - Ignores query strings in module identifiers when matching ".astro" file extensions in Vite plugin

  • #11245 e22be22 Thanks @bluwy! - Refactors prerendering chunk handling to correctly remove unused code during the SSR runtime

4.10.2

Patch Changes

  • #11231 58d7dbb Thanks @ematipico! - Fixes a regression for getViteConfig, where the inline config wasn't merged in the final config.

  • #11228 1e293a1 Thanks @ascorbic! - Updates getCollection() to always return a cloned array

  • #11207 7d9aac3 Thanks @ematipico! - Fixes an issue in the rewriting logic where old data was not purged during the rewrite flow. This caused some false positives when checking the validity of URL path names during the rendering phase.

  • #11189 75a8fe7 Thanks @ematipico! - Improve error message when using getLocaleByPath on path that doesn't contain any locales.

  • #11195 0a6ab6f Thanks @florian-lefebvre! - Adds support for enums to astro:env

    You can now call envField.enum:

    import { defineConfig, envField } from 'astro/config';
    
    export default defineConfig({
      experimental: {
        env: {
          schema: {
            API_VERSION: envField.enum({
              context: 'server',
              access: 'secret',
              values: ['v1', 'v2'],
            }),
          },
        },
      },
    });
    
  • #11210 66fc028 Thanks @matthewp! - Close the iterator only after rendering is complete

  • #11195 0a6ab6f Thanks @florian-lefebvre! - Adds additional validation options to astro:env

    astro:env schema datatypes string and number now have new optional validation rules:

    import { defineConfig, envField } from 'astro/config';
    
    export default defineConfig({
      experimental: {
        env: {
          schema: {
            FOO: envField.string({
              // ...
              max: 32,
              min: 3,
              length: 12,
              url: true,
              includes: 'foo',
              startsWith: 'bar',
              endsWith: 'baz',
            }),
            BAR: envField.number({
              // ...
              gt: 2,
              min: 3,
              lt: 10,
              max: 9,
              int: true,
            }),
          },
        },
      },
    });
    
  • #11211 97724da Thanks @matthewp! - Let middleware handle the original request URL

  • #10607 7327c6a Thanks @frankbits! - Fixes an issue where a leading slash created incorrect conflict resolution between pages generated from static routes and catch-all dynamic routes

4.10.1

Patch Changes

  • #11198 8b9a499 Thanks @florian-lefebvre! - Fixes a case where astro:env getSecret would not retrieve environment variables properly in dev and build modes

  • #11206 734b98f Thanks @florian-lefebvre! - BREAKING CHANGE to the experimental astro:env feature only

    Updates the adapter astro:env entrypoint from astro:env/setup to astro/env/setup

  • #11205 8c45391 Thanks @Nin3lee! - Fixes a typo in the config reference

4.10.0

Minor Changes

  • #10974 2668ef9 Thanks @florian-lefebvre! - Adds experimental support for the astro:env API.

    The astro:env API lets you configure a type-safe schema for your environment variables, and indicate whether they should be available on the server or the client. Import and use your defined variables from the appropriate /client or /server module:

    ---
    import { PUBLIC_APP_ID } from 'astro:env/client';
    import { PUBLIC_API_URL, getSecret } from 'astro:env/server';
    const API_TOKEN = getSecret('API_TOKEN');
    
    const data = await fetch(`${PUBLIC_API_URL}/users`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${API_TOKEN}`,
      },
      body: JSON.stringify({ appId: PUBLIC_APP_ID }),
    });
    ---
    

    To define the data type and properties of your environment variables, declare a schema in your Astro config in experimental.env.schema. The envField helper allows you define your variable as a string, number, or boolean and pass properties in an object:

    // astro.config.mjs
    import { defineConfig, envField } from 'astro/config';
    
    export default defineConfig({
      experimental: {
        env: {
          schema: {
            PUBLIC_API_URL: envField.string({ context: 'client', access: 'public', optional: true }),
            PUBLIC_PORT: envField.number({ context: 'server', access: 'public', default: 4321 }),
            API_SECRET: envField.string({ context: 'server', access: 'secret' }),
          },
        },
      },
    });
    

    There are three kinds of environment variables, determined by the combination of context (client or server) and access (private or public) settings defined in your env.schema:

    • Public client variables: These variables end up in both your final client and server bundles, and can be accessed from both client and server through the astro:env/client module:

      import { PUBLIC_API_URL } from 'astro:env/client';
      
    • Public server variables: These variables end up in your final server bundle and can be accessed on the server through the astro:env/server module:

      import { PUBLIC_PORT } from 'astro:env/server';
      
    • Secret server variables: These variables are not part of your final bundle and can be accessed on the server through the getSecret() helper function available from the astro:env/server module:

      import { getSecret } from 'astro:env/server';
      
      const API_SECRET = getSecret('API_SECRET'); // typed
      const SECRET_NOT_IN_SCHEMA = getSecret('SECRET_NOT_IN_SCHEMA'); // string | undefined
      

    Note: Secret client variables are not supported because there is no safe way to send this data to the client. Therefore, it is not possible to configure both context: "client" and access: "secret" in your schema.

    To learn more, check out the documentation.

Patch Changes

  • #11192 58b10a0 Thanks @liruifengv! - Improves DX by throwing the original AstroUserError when an error is thrown inside a .mdx file.

  • #11136 35ef53c Thanks @ematipico! - Errors that are emitted during a rewrite are now bubbled up and shown to the user. A 404 response is not returned anymore.

  • #11144 803dd80 Thanks @ematipico! - The integration now exposes a function called getContainerRenderer, that can be used inside the Container APIs to load the relative renderer.

    import { experimental_AstroContainer as AstroContainer } from 'astro/container';
    import ReactWrapper from '../src/components/ReactWrapper.astro';
    import { loadRenderers } from 'astro:container';
    import { getContainerRenderer } from '@astrojs/react';
    
    test('ReactWrapper with react renderer', async () => {
      const renderers = await loadRenderers([getContainerRenderer()]);
      const container = await AstroContainer.create({
        renderers,
      });
      const result = await container.renderToString(ReactWrapper);
    
      expect(result).toContain('Counter');
      expect(result).toContain('Count: <!-- -->5');
    });
    
  • #11144 803dd80 Thanks @ematipico! - BREAKING CHANGE to the experimental Container API only

    Changes the type of the renderers option of the AstroContainer::create function and adds a dedicated function loadRenderers() to load the rendering scripts from renderer integration packages (@astrojs/react, @astrojs/preact, @astrojs/solid-js, @astrojs/svelte, @astrojs/vue, @astrojs/lit, and @astrojs/mdx).

    You no longer need to know the individual, direct file paths to the client and server rendering scripts for each renderer integration package. Now, there is a dedicated function to load the renderer from each package, which is available from getContainerRenderer():

    import { experimental_AstroContainer as AstroContainer } from 'astro/container';
    import ReactWrapper from '../src/components/ReactWrapper.astro';
    import { loadRenderers } from "astro:container";
    import { getContainerRenderer } from "@astrojs/react";
    
    test('ReactWrapper with react renderer', async () => {
    + const renderers = await loadRenderers([getContainerRenderer()])
    - const renderers = [
    - {
    -  name: '@astrojs/react',
    -   clientEntrypoint: '@astrojs/react/client.js',
    -   serverEntrypoint: '@astrojs/react/server.js',
    -  },
    - ];
      const container = await AstroContainer.create({
        renderers,
      });
      const result = await container.renderToString(ReactWrapper);
    
      expect(result).toContain('Counter');
      expect(result).toContain('Count: <!-- -->5');
    });
    

    The new loadRenderers() helper function is available from astro:container, a virtual module that can be used when running the Astro container inside vite.

  • #11136 35ef53c Thanks @ematipico! - It's not possible anymore to use Astro.rewrite("/404") inside static pages. This isn't counterproductive because Astro will end-up emitting a page that contains the HTML of 404 error page.

    It's still possible to use Astro.rewrite("/404") inside on-demand pages, or pages that opt-out from prerendering.

  • #11191 6e29a17 Thanks @matthewp! - Fixes a case where Astro.url would be incorrect when having build.format set to 'preserve' in the Astro config

  • #11182 40b0b4d Thanks @ematipico! - Fixes an issue where Astro.rewrite wasn't carrying over the body of a Request in on-demand pages.

  • #11194 97fbe93 Thanks @ematipico! - Fixes an issue where the function getViteConfig wasn't returning the correct merged Astro configuration

4.9.3

Patch Changes

  • #11171 ff8004f Thanks @Princesseuh! - Guard globalThis.astroAsset usage in proxy code to avoid errors in wonky situations

  • #11178 1734c49 Thanks @theoephraim! - Improves isPromise utility to check the presence of then on an object before trying to access it - which can cause undesired side-effects on Proxy objects

  • #11183 3cfa2ac Thanks @66Leo66! - Suggest pnpm dlx instead of pnpx in update check.

  • #11147 2d93902 Thanks @kitschpatrol! - Fixes invalid MIME types in Picture source elements for jpg and svg extensions, which was preventing otherwise valid source variations from being shown by the browser

  • #11141 19df89f Thanks @ematipico! - Fixes an internal error that prevented the AstroContainer to render the Content component.

    You can now write code similar to the following to render content collections:

    const entry = await getEntry(collection, slug);
    const { Content } = await entry.render();
    const content = await container.renderToString(Content);
    
  • #11170 ba20c71 Thanks @matthewp! - Retain client scripts in content cache

4.9.2

Patch Changes

  • #11138 98e0372 Thanks @ematipico! - You can now pass props when rendering a component using the Container APIs:

    import { experimental_AstroContainer as AstroContainer } from 'astro/container';
    import Card from '../src/components/Card.astro';
    
    const container = await AstroContainer.create();
    const result = await container.renderToString(Card, {
      props: {
        someState: true,
      },
    });
    

4.9.1

Patch Changes

4.9.0

Minor Changes

  • #11051 12a1bcc Thanks @ematipico! - Introduces an experimental Container API to render .astro components in isolation.

    This API introduces three new functions to allow you to create a new container and render an Astro component returning either a string or a Response:

    • create(): creates a new instance of the container.
    • renderToString(): renders a component and return a string.
    • renderToResponse(): renders a component and returns the Response emitted by the rendering phase.

    The first supported use of this new API is to enable unit testing. For example, with vitest, you can create a container to render your component with test data and check the result:

    import { experimental_AstroContainer as AstroContainer } from 'astro/container';
    import { expect, test } from 'vitest';
    import Card from '../src/components/Card.astro';
    
    test('Card with slots', async () => {
      const container = await AstroContainer.create();
      const result = await container.renderToString(Card, {
        slots: {
          default: 'Card content',
        },
      });
    
      expect(result).toContain('This is a card');
      expect(result).toContain('Card content');
    });
    

    For a complete reference, see the Container API docs.

    For a feature overview, and to give feedback on this experimental API, see the Container API roadmap discussion.

  • #11021 2d4c8fa Thanks @ematipico! - The CSRF protection feature that was introduced behind a flag in v4.6.0 is no longer experimental and is available for general use.

    To enable the stable version, add the new top-level security option in astro.config.mjs. If you were previously using the experimental version of this feature, also delete the experimental flag:

    export default defineConfig({
    -  experimental: {
    -    security: {
    -      csrfProtection: {
    -        origin: true
    -      }
    -    }
    -  },
    +  security: {
    +    checkOrigin: true
    +  }
    })
    

    Enabling this setting performs a check that the "origin" header, automatically passed by all modern browsers, matches the URL sent by each Request.

    This check is executed only for pages rendered on demand, and only for the requests POST, PATCH, DELETE and PUT with one of the following "content-type" headers: 'application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain'.

    If the "origin" header doesn't match the pathname of the request, Astro will return a 403 status code and won't render the page.

    For more information, see the security configuration docs.

  • #11022 be68ab4 Thanks @ematipico! - The i18nDomains routing feature introduced behind a flag in v3.4.0 is no longer experimental and is available for general use.

    This routing option allows you to configure different domains for individual locales in entirely server-rendered projects using the @astrojs/node or @astrojs/vercel adapter with a site configured.

    If you were using this feature, please remove the experimental flag from your Astro config:

    import { defineConfig } from 'astro'
    
    export default defineConfig({
    -  experimental: {
    -    i18nDomains: true,
    -  }
    })
    

    If you have been waiting for stabilization before using this routing option, you can now do so.

    Please see the internationalization docs for more about this feature.

  • #11071 8ca7c73 Thanks @bholmesdev! - Adds two new functions experimental_getActionState() and experimental_withState() to support the React 19 useActionState() hook when using Astro Actions. This introduces progressive enhancement when calling an Action with the withState() utility.

    This example calls a like action that accepts a postId and returns the number of likes. Pass this action to the experimental_withState() function to apply progressive enhancement info, and apply to useActionState() to track the result:

    import { actions } from 'astro:actions';
    import { experimental_withState } from '@astrojs/react/actions';
    
    export function Like({ postId }: { postId: string }) {
      const [state, action, pending] = useActionState(
        experimental_withState(actions.like),
        0, // initial likes
      );
    
      return (
        <form action={action}>
          <input type="hidden" name="postId" value={postId} />
          <button disabled={pending}>{state} ❤️</button>
        </form>
      );
    }
    

    You can also access the state stored by useActionState() from your action handler. Call experimental_getActionState() with the API context, and optionally apply a type to the result:

    import { defineAction, z } from 'astro:actions';
    import { experimental_getActionState } from '@astrojs/react/actions';
    
    export const server = {
      like: defineAction({
        input: z.object({
          postId: z.string(),
        }),
        handler: async ({ postId }, ctx) => {
          const currentLikes = experimental_getActionState<number>(ctx);
          // write to database
          return currentLikes + 1;
        },
      }),
    };
    
  • #11101 a6916e4 Thanks @linguofeng! - Updates Astro's code for adapters to use the header x-forwarded-for to initialize the clientAddress.

    To take advantage of the new change, integration authors must upgrade the version of Astro in their adapter peerDependencies to 4.9.0.

  • #11071 8ca7c73 Thanks @bholmesdev! - Adds compatibility for Astro Actions in the React 19 beta. Actions can be passed to a form action prop directly, and Astro will automatically add metadata for progressive enhancement.

    import { actions } from 'astro:actions';
    
    function Like() {
      return (
        <form action={actions.like}>
          {/* auto-inserts hidden input for progressive enhancement */}
          <button type="submit">Like</button>
        </form>
      );
    }
    

Patch Changes

  • #11088 9566fa0 Thanks @bholmesdev! - Allow actions to be called on the server. This allows you to call actions as utility functions in your Astro frontmatter, endpoints, and server-side UI components.

    Import and call directly from astro:actions as you would for client actions:

    ---
    // src/pages/blog/[postId].astro
    import { actions } from 'astro:actions';
    
    await actions.like({ postId: Astro.params.postId });
    ---
    
  • #11112 29a8650 Thanks @bholmesdev! - Deprecate the getApiContext() function. API Context can now be accessed from the second parameter to your Action handler():

    // src/actions/index.ts
    import {
      defineAction,
      z,
    -  getApiContext,
    } from 'astro:actions';
    
    export const server = {
      login: defineAction({
        input: z.object({ id: z.string }),
    +    handler(input, context) {
          const user = context.locals.auth(input.id);
          return user;
        }
      }),
    }
    

4.8.7

Patch Changes

  • #11073 f5c8fee Thanks @matthewp! - Prevent cache content from being left in dist folder

    When contentCollectionsCache is enabled temporary cached content is copied into the outDir for processing. This fixes it so that this content is cleaned out, along with the rest of the temporary build JS.

  • #11054 f6b171e Thanks @bholmesdev! - Respect error status when handling Actions with a progressive fallback.

  • #11092 bfe9c73 Thanks @duckycoding-dev! - Change slot attribute of IntrinsicAttributes to match the definition of HTMLAttributes's own slot attribute of type string | undefined | null

  • #10875 b5f95b2 Thanks @W1M0R! - Fixes a typo in a JSDoc annotation

  • #11111 a5d79dd Thanks @bholmesdev! - Fix unexpected headers warning on prerendered routes when using Astro Actions.

  • #11081 af42e05 Thanks @V3RON! - Correctly position inspection tooltip in RTL mode

    When RTL mode is turned on, the inspection tooltip tend to overflow the window on the left side. Additional check has been added to prevent that.

4.8.6

Patch Changes

  • #11084 9637014 Thanks @bluwy! - Fixes regression when handling hoisted scripts from content collections

4.8.5

Patch Changes

4.8.4

Patch Changes

  • #11026 8dfb1a2 Thanks @bluwy! - Skips rendering script tags if it's inlined and empty when experimental.directRenderScript is enabled

  • #11043 d0d1710 Thanks @bholmesdev! - Fixes minor type issues in actions component example

  • #10999 5f353e3 Thanks @bluwy! - The prefetch feature is updated to better support different browsers and different cache headers setup, including:

    1. All prefetch strategies will now always try to use <link rel="prefetch"> if supported, or will fall back to fetch().
    2. The prefetch() programmatic API's with option is deprecated in favour of an automatic approach that will also try to use <link rel="prefetch> if supported, or will fall back to fetch().

    This change shouldn't affect most sites and should instead make prefetching more effective.

  • #11041 6cc3fb9 Thanks @bholmesdev! - Fixes 500 errors when sending empty params or returning an empty response from an action.

  • #11028 771d1f7 Thanks @bholmesdev! - Throw on missing server output when using Astro Actions.

  • #11029 bd34452 Thanks @bholmesdev! - Actions: include validation error in thrown error message for debugging.

  • #11046 086694a Thanks @HiDeoo! - Fixes getViteConfig() type definition to allow passing an inline Astro configuration as second argument

  • #11026 8dfb1a2 Thanks @bluwy! - Fixes CSS handling if imported in a script tag in an Astro file when experimental.directRenderScript is enabled

  • #11020 2e2d6b7 Thanks @xsynaptic! - Add type declarations for import.meta.env.ASSETS_PREFIX when defined as an object for handling different file types.

  • #11030 18e7f33 Thanks @bholmesdev! - Actions: Fix missing message for custom Action errors.

  • #10981 ad9227c Thanks @mo! - Adds deprecated HTML attribute "name" to the list of valid attributes. This attribute has been replaced by the global id attribute in recent versions of HTML.

  • #11013 4ea38e7 Thanks @QingXia-Ela! - Prevents unhandledrejection error when checking for latest Astro version

  • #11034 5f2dd45 Thanks @arganaphang! - Add popovertargetaction to the attribute that can be passed to the button and input element

4.8.3

Patch Changes

4.8.2

Patch Changes

4.8.1

Patch Changes

  • #10987 05db5f7 Thanks @ematipico! - Fix a regression where the flag experimental.rewriting was marked mandatory. Is is now optional.

  • #10975 6b640b3 Thanks @bluwy! - Passes the scoped style attribute or class to the <picture> element in the <Picture /> component so scoped styling can be applied to the <picture> element

4.8.0

Minor Changes

  • #10935 ddd8e49 Thanks @bluwy! - Exports astro/jsx/rehype.js with utilities to generate an Astro metadata object

  • #10625 698c2d9 Thanks @goulvenclech! - Adds the ability for multiple pages to use the same component as an entrypoint when building an Astro integration. This change is purely internal, and aligns the build process with the behaviour in the development server.

  • #10906 7bbd664 Thanks @Princesseuh! - Adds a new radio checkbox component to the dev toolbar UI library (astro-dev-toolbar-radio-checkbox)

  • #10963 61f47a6 Thanks @delucis! - Adds support for passing an inline Astro configuration object to getViteConfig()

    If you are using getViteConfig() to configure the Vitest test runner, you can now pass a second argument to control how Astro is configured. This makes it possible to configure unit tests with different Astro options when using Vitests workspaces feature.

    // vitest.config.ts
    import { getViteConfig } from 'astro/config';
    
    export default getViteConfig(
      /* Vite configuration */
      { test: {} },
      /* Astro configuration */
      {
        site: 'https://example.com',
        trailingSlash: 'never',
      },
    );
    
  • #10867 47877a7 Thanks @ematipico! - Adds experimental rewriting in Astro with a new rewrite() function and the middleware next() function.

    The feature is available via an experimental flag in astro.config.mjs:

    export default defineConfig({
      experimental: {
        rewriting: true,
      },
    });
    

    When enabled, you can use rewrite() to render another page without changing the URL of the browser in Astro pages and endpoints.

    ---
    // src/pages/dashboard.astro
    if (!Astro.props.allowed) {
      return Astro.rewrite('/');
    }
    ---
    
    // src/pages/api.js
    export function GET(ctx) {
      if (!ctx.locals.allowed) {
        return ctx.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
    export function onRequest(ctx, next) {
      if (!ctx.cookies.get('allowed')) {
        return next('/'); // new signature
      }
      return next();
    }
    

    NOTE: please read the RFC to understand the current expectations of the new APIs.

  • #10858 c0c509b Thanks @bholmesdev! - Adds experimental support for the Actions API. Actions let you define type-safe endpoints you can query from client components with progressive enhancement built in.

    Actions help you write type-safe backend functions you can call from anywhere. Enable server rendering using the output property and add the actions flag to the experimental object:

    {
      output: 'hybrid', // or 'server'
      experimental: {
        actions: true,
      },
    }
    

    Declare all your actions in src/actions/index.ts. This file is the global actions handler.

    Define an action using the defineAction() utility from the astro:actions module. These accept the handler property to define your server-side request handler. If your action accepts arguments, apply the input property to validate parameters with Zod.

    This example defines two actions: like and comment. The like action accepts a JSON object with a postId string, while the comment action accepts FormData with postId, author, and body strings. Each handler updates your database and return a type-safe response.

    // src/actions/index.ts
    import { defineAction, z } from 'astro:actions';
    
    export const server = {
      like: defineAction({
        input: z.object({ postId: z.string() }),
        handler: async ({ postId }) => {
          // update likes in db
    
          return likes;
        },
      }),
      comment: defineAction({
        accept: 'form',
        input: z.object({
          postId: z.string(),
    
          body: z.string(),
        }),
        handler: async ({ postId }) => {
          // insert comments in db
    
          return comment;
        },
      }),
    };
    

    Then, call an action from your client components using the actions object from astro:actions. You can pass a type-safe object when using JSON, or a FormData object when using accept: 'form' in your action definition:

    // src/components/blog.tsx
    import { actions } from 'astro:actions';
    import { useState } from 'preact/hooks';
    
    export function Like({ postId }: { postId: string }) {
      const [likes, setLikes] = useState(0);
      return (
        <button
          onClick={async () => {
            const newLikes = await actions.like({ postId });
            setLikes(newLikes);
          }}
        >
          {likes} likes
        </button>
      );
    }
    
    export function Comment({ postId }: { postId: string }) {
      return (
        <form
          onSubmit={async (e) => {
            e.preventDefault();
            const formData = new FormData(e.target);
            const result = await actions.blog.comment(formData);
            // handle result
          }}
        >
          <input type="hidden" name="postId" value={postId} />
          <label for="author">Author</label>
          <input id="author" type="text" name="author" />
          <textarea rows={10} name="body"></textarea>
          <button type="submit">Post</button>
        </form>
      );
    }
    

    For a complete overview, and to give feedback on this experimental API, see the Actions RFC.

  • #10906 7bbd664 Thanks @Princesseuh! - Adds a new buttonBorderRadius property to the astro-dev-toolbar-button component for the dev toolbar component library. This property can be useful to make a fully rounded button with an icon in the center.

Patch Changes

  • #10977 59571e8 Thanks @BryceRussell! - Improve error message when accessing clientAddress on prerendered routes

  • #10935 ddd8e49 Thanks @bluwy! - Improves the error message when failed to render MDX components

  • #10917 3412535 Thanks @jakobhellermann! - Fixes a case where the local server would crash when the host also contained the port, eg. with X-Forwarded-Host: hostname:8080 and X-Forwarded-Port: 8080 headers

  • #10959 685fc22 Thanks @bluwy! - Refactors internal handling of styles and scripts for content collections to improve build performance

  • #10889 4d905cc Thanks @matthewp! - Preserve content modules properly in cache

  • #10955 2978287 Thanks @florian-lefebvre! - Handles AstroUserErrors thrown while syncing content collections and exports BaseSchema and CollectionConfig types

4.7.1

Patch Changes

  • #10911 a86dc9d Thanks @bluwy! - Skips adding CSS dependencies of CSS Vite modules as style tags in the HTML

  • #10900 36bb3b6 Thanks @martrapp! - Detects overlapping navigation and view transitions and automatically aborts all but the most recent one.

  • #10933 007d17f Thanks @Princesseuh! - Fixes app.toggleState not working correctly

  • #10931 4ce5ced Thanks @ktym4a! - Fixes toggleNotification()'s parameter type for the notification level not using the proper levels

4.7.0

Minor Changes

  • #10665 7b4f284 Thanks @Princesseuh! - Adds new utilities to ease the creation of toolbar apps including defineToolbarApp to make it easier to define your toolbar app and app and server helpers for easier communication between the toolbar and the server. These new utilities abstract away some of the boilerplate code that is common in toolbar apps, and lower the barrier of entry for app authors.

    For example, instead of creating an event listener for the app-toggled event and manually typing the value in the callback, you can now use the onAppToggled method. Additionally, communicating with the server does not require knowing any of the Vite APIs anymore, as a new server object is passed to the init function that contains easy to use methods for communicating with the server.

    import { defineToolbarApp } from "astro/toolbar";
    
    export default defineToolbarApp({
      init(canvas, app, server) {
    
    -    app.addEventListener("app-toggled", (e) => {
    -      console.log(`App is now ${state ? "enabled" : "disabled"}`);.
    -    });
    
    +    app.onToggled(({ state }) => {
    +        console.log(`App is now ${state ? "enabled" : "disabled"}`);
    +    });
    
    -    if (import.meta.hot) {
    -      import.meta.hot.send("my-app:my-client-event", { message: "world" });
    -    }
    
    +    server.send("my-app:my-client-event", { message: "world" })
    
    -    if (import.meta.hot) {
    -      import.meta.hot.on("my-server-event", (data: {message: string}) => {
    -        console.log(data.message);
    -      });
    -    }
    
    +    server.on<{ message: string }>("my-server-event", (data) => {
    +      console.log(data.message); // data is typed using the type parameter
    +    });
      },
    })
    

    Server helpers are also available on the server side, for use in your integrations, through the new toolbar object:

    "astro:server:setup": ({ toolbar }) => {
      toolbar.on<{ message: string }>("my-app:my-client-event", (data) => {
        console.log(data.message);
        toolbar.send("my-server-event", { message: "hello" });
      });
    }
    

    This is a backwards compatible change and your your existing dev toolbar apps will continue to function. However, we encourage you to build your apps with the new helpers, following the updated Dev Toolbar API documentation.

  • #10734 6fc4c0e Thanks @Princesseuh! - Astro will now automatically check for updates when you run the dev server. If a new version is available, a message will appear in the terminal with instructions on how to update. Updates will be checked once per 10 days, and the message will only appear if the project is multiple versions behind the latest release.

    This behavior can be disabled by running astro preferences disable checkUpdates or setting the ASTRO_DISABLE_UPDATE_CHECK environment variable to false.

  • #10762 43ead8f Thanks @bholmesdev! - Enables type checking for JavaScript files when using the strictest TS config. This ensures consistency with Astro's other TS configs, and fixes type checking for integrations like Astro DB when using an astro.config.mjs.

    If you are currently using the strictest preset and would like to still disable .js files, set allowJS: false in your tsconfig.json.

Patch Changes

  • #10861 b673bc8 Thanks @mingjunlu! - Fixes an issue where astro build writes type declaration files to outDir when it's outside of root directory.

  • #10684 8b59d5d Thanks @PeterDraex! - Update sharp to 0.33 to fix issue with Alpine Linux

4.6.4

Patch Changes

  • #10846 3294f7a Thanks @matthewp! - Prevent getCollection breaking in vitest

  • #10856 30cf82a Thanks @robertvanhoesel! - Prevents inputs with a name attribute of action or method to break ViewTransitions' form submission

  • #10833 8d5f3e8 Thanks @renovate! - Updates esbuild dependency to v0.20. This should not affect projects in most cases.

  • #10801 204b782 Thanks @rishi-raj-jain! - Fixes an issue where images in MD required a relative specifier (e.g. ./)

    Now, you can use the standard ![](relative/img.png) syntax in MD files for images colocated in the same folder: no relative specifier required!

    There is no need to update your project; your existing images will still continue to work. However, you may wish to remove any relative specifiers from these MD images as they are no longer necessary:

    - ![A cute dog](./dog.jpg)
    + ![A cute dog](dog.jpg)
    <!-- This dog lives in the same folder as my article! -->
    
  • #10841 a2df344 Thanks @martrapp! - Due to regression on mobile WebKit browsers, reverts a change made for JavaScript animations during view transitions.

4.6.3

Patch Changes

4.6.2

Patch Changes

4.6.1

Patch Changes

4.6.0

Minor Changes

  • #10591 39988ef8e2c4c4888543c973e06d9b9939e4ac95 Thanks @mingjunlu! - Adds a new dev toolbar settings option to change the horizontal placement of the dev toolbar on your screen: bottom left, bottom center, or bottom right.

  • #10689 683d51a5eecafbbfbfed3910a3f1fbf0b3531b99 Thanks @ematipico! - Deprecate support for versions of Node.js older than v18.17.1 for Node.js 18, older than v20.0.3 for Node.js 20, and the complete Node.js v19 release line.

    This change is in line with Astro's Node.js support policy.

  • #10678 2e53b5fff6d292b7acdf8c30a6ecf5e5696846a1 Thanks @ematipico! - Adds a new experimental security option to prevent Cross-Site Request Forgery (CSRF) attacks. This feature is available only for pages rendered on demand:

    import { defineConfig } from 'astro/config';
    export default defineConfig({
      experimental: {
        security: {
          csrfProtection: {
            origin: true,
          },
        },
      },
    });
    

    Enabling this setting performs a check that the "origin" header, automatically passed by all modern browsers, matches the URL sent by each Request.

    This experimental "origin" check is executed only for pages rendered on demand, and only for the requests POST, PATCH, DELETEandPUTwith one of the followingcontent-type` headers: 'application/x-www-form-urlencoded', 'multipart/form-data', 'text/plain'.

    It the "origin" header doesn't match the pathname of the request, Astro will return a 403 status code and won't render the page.

  • #10193 440681e7b74511a17b152af0fd6e0e4dc4014025 Thanks @ematipico! - Adds a new i18n routing option manual to allow you to write your own i18n middleware:

    import { defineConfig } from 'astro/config';
    // astro.config.mjs
    export default defineConfig({
      i18n: {
        locales: ['en', 'fr'],
        defaultLocale: 'fr',
        routing: 'manual',
      },
    });
    

    Adding routing: "manual" to your i18n config disables Astro's own i18n middleware and provides you with helper functions to write your own: redirectToDefaultLocale, notFound, and redirectToFallback:

    // middleware.js
    import { redirectToDefaultLocale } from 'astro:i18n';
    export const onRequest = defineMiddleware(async (context, next) => {
      if (context.url.startsWith('/about')) {
        return next();
      } else {
        return redirectToDefaultLocale(context, 302);
      }
    });
    

    Also adds a middleware function that manually creates Astro's i18n middleware. This allows you to extend Astro's i18n routing instead of completely replacing it. Run middleware in combination with your own middleware, using the sequence utility to determine the order:

    import { defineMiddleware, sequence } from 'astro:middleware';
    import { middleware } from 'astro:i18n'; // Astro's own i18n routing config
    
    export const userMiddleware = defineMiddleware();
    
    export const onRequest = sequence(
      userMiddleware,
      middleware({
        redirectToDefaultLocale: false,
        prefixDefaultLocale: true,
      }),
    );
    
  • #10671 9e14a78cb05667af9821948c630786f74680090d Thanks @fshafiee! - Adds the httpOnly, sameSite, and secure options when deleting a cookie

Patch Changes

4.5.18

Patch Changes

4.5.17

Patch Changes

4.5.16

Patch Changes

4.5.15

Patch Changes

4.5.14

Patch Changes

4.5.13

Patch Changes

4.5.12

Patch Changes

4.5.11

Patch Changes

4.5.10

Patch Changes

4.5.9

Patch Changes

4.5.8

Patch Changes

4.5.7

Patch Changes

4.5.6

Patch Changes

4.5.5

Patch Changes

4.5.4

Patch Changes

4.5.3

Patch Changes

4.5.2

Patch Changes

4.5.1

Patch Changes

4.5.0

Minor Changes

  • #10206 dc87214141e7f8406c0fdf6a7f425dad6dea6d3e Thanks @lilnasy! - Allows middleware to run when a matching page or endpoint is not found. Previously, a pages/404.astro or pages/[...catch-all].astro route had to match to allow middleware. This is now not necessary.

    When a route does not match in SSR deployments, your adapter may show a platform-specific 404 page instead of running Astro's SSR code. In these cases, you may still need to add a 404.astro or fallback route with spread params, or use a routing configuration option if your adapter provides one.

  • #9960 c081adf998d30419fed97d8fccc11340cdc512e0 Thanks @StandardGage! - Allows passing any props to the <Code /> component

  • #10102 e3f02f5fb1cf0dae3c54beb3a4af3dbf3b06abb7 Thanks @bluwy! - Adds a new experimental.directRenderScript configuration option which provides a more reliable strategy to prevent scripts from being executed in pages where they are not used.

    This replaces the experimental.optimizeHoistedScript flag introduced in v2.10.4 to prevent unused components' scripts from being included in a page unexpectedly. That experimental option no longer exists and must be removed from your configuration, whether or not you enable directRenderScript:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
    	experimental: {
    -		optimizeHoistedScript: true,
    +		directRenderScript: true
    	}
    });
    

    With experimental.directRenderScript configured, scripts are now directly rendered 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> and multiple scripts on a page are no longer bundled together. If you enable this option, you should check that all your <script> tags behave as expected.

    This option will be enabled by default in Astro 5.0.

  • #10130 5a9528741fa98d017b269c7e4f013058028bdc5d Thanks @bluwy! - Stabilizes markdown.shikiConfig.experimentalThemes as markdown.shikiConfig.themes. No behaviour changes are made to this option.

  • #10189 1ea0a25b94125e4f6f2ac82b42f638e22d7bdffd Thanks @peng! - Adds the option to pass an object to build.assetsPrefix. This allows for the use of multiple CDN prefixes based on the target file type.

    When passing an object to build.assetsPrefix, you must also specify a fallback domain to be used for all other file types not specified.

    Specify a file extension as the key (e.g. 'js', 'png') and the URL serving your assets of that file type as the value:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      build: {
        assetsPrefix: {
          js: 'https://js.cdn.example.com',
          mjs: 'https://js.cdn.example.com', // if you have .mjs files, you must add a new entry like this
          png: 'https://images.cdn.example.com',
          fallback: 'https://generic.cdn.example.com',
        },
      },
    });
    
  • #10252 3307cb34f17159dfd3f03144697040fcaa10e903 Thanks @Princesseuh! - Adds support for emitting warning and info notifications from dev toolbar apps.

    When using the toggle-notification event, the severity can be specified through detail.level:

    eventTarget.dispatchEvent(
      new CustomEvent('toggle-notification', {
        detail: {
          level: 'warning',
        },
      }),
    );
    
  • #10186 959ca5f9f86ef2c0a5a23080cc01c25f53d613a9 Thanks @Princesseuh! - Adds the ability to set colors on all the included UI elements for dev toolbar apps. Previously, only badge and buttons could be customized.

  • #10136 9cd84bd19b92fb43ae48809f575ee12ebd43ea8f Thanks @matthewp! - Changes the default behavior of transition:persist to update the props of persisted islands upon navigation. Also adds a new view transitions option transition:persist-props (default: false) to prevent props from updating as needed.

    Islands which have the transition:persist property to keep their state when using the <ViewTransitions /> router will now have their props updated upon navigation. This is useful in cases where the component relies on page-specific props, such as the current page title, which should update upon navigation.

    For example, the component below is set to persist across navigation. This component receives a products props and might have some internal state, such as which filters are applied:

    <ProductListing transition:persist products={products} />
    

    Upon navigation, this component persists, but the desired products might change, for example if you are visiting a category of products, or you are performing a search.

    Previously the props would not change on navigation, and your island would have to handle updating them externally, such as with API calls.

    With this change the props are now updated, while still preserving state.

    You can override this new default behavior on a per-component basis using transition:persist-props=true to persist both props and state during navigation:

    <ProductListing transition:persist-props="true" products={products} />
    
  • #9977 0204b7de37bf626e1b97175b605adbf91d885386 Thanks @OliverSpeir! - Supports adding the data-astro-rerun attribute on script tags so that they will be re-executed after view transitions

    <script is:inline data-astro-rerun>
      ...
    </script>
    
  • #10145 65692fa7b5f4440c644c8cf3dd9bc50103d2c33b Thanks @alexanderniebuhr! - Adds experimental JSON Schema support for content collections.

    This feature will auto-generate a JSON Schema for content collections of type: 'data' which can be used as the $schema value for TypeScript-style autocompletion/hints in tools like VSCode.

    To enable this feature, add the experimental flag:

    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
    	experimental: {
    +		contentCollectionJsonSchema: true
    	}
    });
    

    This experimental implementation requires you to manually reference the schema in each data entry file of the collection:

    // src/content/test/entry.json
    {
    +  "$schema": "../../../.astro/collections/test.schema.json",
      "test": "test"
    }
    

    Alternatively, you can set this in your VSCode json.schemas settings:

    "json.schemas": [
      {
        "fileMatch": [
          "/src/content/test/**"
        ],
        "url": "../../../.astro/collections/test.schema.json"
      }
    ]
    

    Note that this initial implementation uses a library with known issues for advanced Zod schemas, so you may wish to consult these limitations before enabling the experimental flag.

  • #10130 5a9528741fa98d017b269c7e4f013058028bdc5d Thanks @bluwy! - Migrates shikiji to shiki 1.0

  • #10268 2013e70bce16366781cc12e52823bb257fe460c0 Thanks @Princesseuh! - Adds support for page mutations to the audits in the dev toolbar. Astro will now rerun the audits whenever elements are added or deleted from the page.

  • #10217 5c7862a9fe69954f8630538ebb7212cd04b8a810 Thanks @Princesseuh! - Updates the UI for dev toolbar audits with new information

Patch Changes

4.4.15

Patch Changes

4.4.14

Patch Changes

4.4.13

Patch Changes

4.4.12

Patch Changes

4.4.11

Patch Changes

4.4.10

Patch Changes

4.4.9

Patch Changes

4.4.8

Patch Changes

4.4.7

Patch Changes

4.4.6

Patch Changes

4.4.5

Patch Changes

4.4.4

Patch Changes

4.4.3

Patch Changes

4.4.2

Patch Changes

4.4.1

Patch Changes

4.4.0

Minor Changes

  • #9614 d469bebd7b45b060dc41d82ab1cf18ee6de7e051 Thanks @matthewp! - Improves Node.js streaming performance.

    This uses an AsyncIterable instead of a ReadableStream to do streaming in Node.js. This is a non-standard enhancement by Node, which is done only in that environment.

  • #10001 748b2e87cd44d8bcc1ab9d7e504703057e2000cd Thanks @bholmesdev! - Removes content collection warning when a configured collection does not have a matching directory name. This should resolve i18n collection warnings for Starlight users.

    This also ensures configured collection names are always included in getCollection() and getEntry() types even when a matching directory is absent. We hope this allows users to discover typos during development by surfacing type information.

  • #10074 7443929381b47db0639c49a4d32aec4177bd9102 Thanks @Princesseuh! - Add a UI showing the list of found problems when using the audit app in the dev toolbar

  • #10099 b340f8fe3aaa81e38c4f1aa41498b159dc733d86 Thanks @martrapp! - Fixes a regression where view transition names containing special characters such as spaces or punctuation stopped working.

    Regular use naming your transitions with transition: name is unaffected.

    However, this fix may result in breaking changes if your project relies on the particular character encoding strategy Astro uses to translate transition:name directives into values of the underlying CSS view-transition-name property. For example, Welcome to Astro is now encoded as Welcome_20to_20Astro_2e.

    This mainly affects spaces and punctuation marks but no Unicode characters with codes >= 128.

  • #9976 91f75afbc642b6e73dd4ec18a1fe2c3128c68132 Thanks @OliverSpeir! - Adds a new optional astro:assets image attribute inferSize for use with remote images.

    Remote images can now have their dimensions inferred just like local images. Setting inferSize to true allows you to use getImage() and the <Image /> and <Picture /> components without setting the width and height properties.

    ---
    import { Image, Picture, getImage } from 'astro:assets';
    const myPic = await getImage({ src: 'https://example.com/example.png', inferSize: true });
    ---
    
    <Image src="https://example.com/example.png" inferSize alt="" />
    <Picture src="https://example.com/example.png" inferSize alt="" />
    

    Read more about using inferSize with remote images in our documentation.

  • #10015 6884b103c8314a43e926c6acdf947cbf812a21f4 Thanks @Princesseuh! - Adds initial support for performance audits to the dev toolbar

Patch Changes

  • #10116 4bcc249a9f34aaac59658ca626c828bd6dbb8046 Thanks @lilnasy! - Fixes an issue where the dev server froze when typescript aliases were used.

  • #10096 227cd83a51bbd451dc223fd16f4cf1b87b8e44f8 Thanks @Fryuni! - Fixes regression on routing priority for multi-layer index pages

    The sorting algorithm positions more specific routes before less specific routes, and considers index pages to be more specific than a dynamic route with a rest parameter inside of it. This means that /blog is considered more specific than /blog/[...slug].

    But this special case was being applied incorrectly to indexes, which could cause a problem in scenarios like the following:

    • /
    • /blog
    • /blog/[...slug]

    The algorithm would make the following comparisons:

    • / is more specific than /blog (incorrect)
    • /blog/[...slug] is more specific than / (correct)
    • /blog is more specific than /blog/[...slug] (correct)

    Although the incorrect first comparison is not a problem by itself, it could cause the algorithm to make the wrong decision. Depending on the other routes in the project, the sorting could perform just the last two comparisons and by transitivity infer the inverse of the third (/blog/[...slug > / > /blog), which is incorrect.

    Now the algorithm doesn't have a special case for index pages and instead does the comparison soleley for rest parameter segments and their immediate parents, which is consistent with the transitivity property.

  • #10120 787e6f52470cf07fb50c865948b2bc8fe45a6d31 Thanks @bluwy! - Updates and supports Vite 5.1

  • #10096 227cd83a51bbd451dc223fd16f4cf1b87b8e44f8 Thanks @Fryuni! - Fixes edge case on i18n fallback routes

    Previously index routes deeply nested in the default locale, like /some/nested/index.astro could be mistaked as the root index for the default locale, resulting in an incorrect redirect on /.

  • #10112 476b79a61165d0aac5e98459a4ec90762050a14b Thanks @Princesseuh! - Renames the home Astro Devoolbar App to astro:home

  • #10117 51b6ff7403c1223b1c399e88373075972c82c24c Thanks @hippotastic! - Fixes an issue where create astro, astro add and @astrojs/upgrade would fail due to unexpected package manager CLI output.

4.3.7

Patch Changes

4.3.6

Patch Changes

4.3.5

Patch Changes

4.3.4

Patch Changes

4.3.3

Patch Changes

4.3.2

Patch Changes

4.3.1

Patch Changes

4.3.0

Minor Changes

  • #9839 58f9e393a188702eef5329e41deff3dcb65a3230 Thanks @Princesseuh! - Adds a new ComponentProps type export from astro/types to get the props type of an Astro component.

    ---
    import type { ComponentProps } from 'astro/types';
    import Button from './Button.astro';
    
    type myButtonProps = ComponentProps<typeof Button>;
    ---
    
  • #9159 7d937c158959e76443a02f740b10e251d14dbd8c Thanks @bluwy! - Adds CLI shortcuts as an easter egg for the dev server:

    • o + enter: opens the site in your browser
    • q + enter: quits the dev server
    • h + enter: prints all available shortcuts
  • #9764 fad4f64aa149086feda2d1f3a0b655767034f1a8 Thanks @matthewp! - Adds a new build.format configuration option: 'preserve'. This option will preserve your source structure in the final build.

    The existing configuration options, file and directory, either build all of your HTML pages as files matching the route name (e.g. /about.html) or build all your files as index.html within a nested directory structure (e.g. /about/index.html), respectively. It was not previously possible to control the HTML file built on a per-file basis.

    One limitation of build.format: 'file' is that it cannot create index.html files for any individual routes (other than the base path of /) while otherwise building named files. Creating explicit index pages within your file structure still generates a file named for the page route (e.g. src/pages/about/index.astro builds /about.html) when using the file configuration option.

    Rather than make a breaking change to allow build.format: 'file' to be more flexible, we decided to create a new build.format: 'preserve'.

    The new format will preserve how the filesystem is structured and make sure that is mirrored over to production. Using this option:

    • about.astro becomes about.html
    • about/index.astro becomes about/index.html

    See the build.format configuration options reference for more details.

  • #9143 041fdd5c89920f7ccf944b095f29e451f78b0e28 Thanks @ematipico! - Adds experimental support for a new i18n domain routing option ("domains") that allows you to configure different domains for individual locales in entirely server-rendered projects.

    To enable this in your project, first configure your server-rendered project's i18n routing with your preferences if you have not already done so. Then, set the experimental.i18nDomains flag to true and add i18n.domains to map any of your supported locales to custom URLs:

    //astro.config.mjs"
    import { defineConfig } from 'astro/config';
    export default defineConfig({
      site: 'https://example.com',
      output: 'server', // required, with no prerendered pages
      adapter: node({
        mode: 'standalone',
      }),
      i18n: {
        defaultLocale: 'en',
        locales: ['es', 'en', 'fr', 'ja'],
        routing: {
          prefixDefaultLocale: false,
        },
        domains: {
          fr: 'https://fr.example.com',
          es: 'https://example.es',
        },
      },
      experimental: {
        i18nDomains: true,
      },
    });
    

    With "domains" configured, the URLs emitted by getAbsoluteLocaleUrl() and getAbsoluteLocaleUrlList() will use the options set in i18n.domains.

    import { getAbsoluteLocaleUrl } from 'astro:i18n';
    
    getAbsoluteLocaleUrl('en', 'about'); // will return "https://example.com/about"
    getAbsoluteLocaleUrl('fr', 'about'); // will return "https://fr.example.com/about"
    getAbsoluteLocaleUrl('es', 'about'); // will return "https://example.es/about"
    getAbsoluteLocaleUrl('ja', 'about'); // will return "https://example.com/ja/about"
    

    Similarly, your localized files will create routes at corresponding URLs:

    • The file /en/about.astro will be reachable at the URL https://example.com/about.
    • The file /fr/about.astro will be reachable at the URL https://fr.example.com/about.
    • The file /es/about.astro will be reachable at the URL https://example.es/about.
    • The file /ja/about.astro will be reachable at the URL https://example.com/ja/about.

    See our Internationalization Guide for more details and limitations on this experimental routing feature.

  • #9755 d4b886141bb342ac71b1c060e67d66ca2ffbb8bd Thanks @OliverSpeir! - Fixes an issue where images in Markdown required a relative specifier (e.g. ./)

    Now, you can use the standard ![](img.png) syntax in Markdown files for images colocated in the same folder: no relative specifier required!

    There is no need to update your project; your existing images will still continue to work. However, you may wish to remove any relative specifiers from these Markdown images as they are no longer necessary:

    - ![A cute dog](./dog.jpg)
    + ![A cute dog](dog.jpg)
    <!-- This dog lives in the same folder as my article! -->
    

Patch Changes

4.2.8

Patch Changes

4.2.7

Patch Changes

4.2.6

Patch Changes

4.2.5

Patch Changes

4.2.4

Patch Changes

  • #9792 e22cb8b10c0ca9f6d88cab53cd2713f57875ab4b Thanks @tugrulates! - Accept aria role switch on toolbar audit.

  • #9606 e6945bcf23b6ad29388bbadaf5bb3cc31dd4a114 Thanks @eryue0220! - Fixes escaping behavior for .html files and components

  • #9786 5b29550996a7f5459a0d611feea6e51d44e1d8ed Thanks @Fryuni! - Fixes a regression in routing priority for index pages in rest parameter folders and dynamic sibling trees.

    Considering the following tree:

    src/pages/
    ├── index.astro
    ├── static.astro
    ├── [dynamic_file].astro
    ├── [...rest_file].astro
    ├── blog/
    │   └── index.astro
    ├── [dynamic_folder]/
    │   ├── index.astro
    │   ├── static.astro
    │   └── [...rest].astro
    └── [...rest_folder]/
        ├── index.astro
        └── static.astro
    

    The routes are sorted in this order:

    /src/pages/index.astro
    /src/pages/blog/index.astro
    /src/pages/static.astro
    /src/pages/[dynamic_folder]/index.astro
    /src/pages/[dynamic_file].astro
    /src/pages/[dynamic_folder]/static.astro
    /src/pages/[dynamic_folder]/[...rest].astro
    /src/pages/[...rest_folder]/static.astro
    /src/pages/[...rest_folder]/index.astro
    /src/pages/[...rest_file]/index.astro
    

    This allows for index files to be used as overrides to rest parameter routes on SSR when the rest parameter matching undefined is not desired.

  • #9775 075706f26d2e11e66ef8b52288d07e3c0fa97eb1 Thanks @lilnasy! - Simplifies internals that handle endpoints.

  • #9773 9aa7a5368c502ae488d3a173e732d81f3d000e98 Thanks @LunaticMuch! - Raises the required vite version to address a vulnerability in vite.server.fs.deny that affected the dev mode.

  • #9781 ccc05d54014e24c492ca5fddd4862f318aac8172 Thanks @stevenbenner! - Fix build failure when image file name includes special characters

4.2.3

Patch Changes

4.2.2

Patch Changes

4.2.1

Patch Changes

4.2.0

Minor Changes

  • #9566 165cfc154be477337037185c32b308616d1ed6fa Thanks @OliverSpeir! - Allows remark plugins to pass options specifying how images in .md files will be optimized

  • #9661 d6edc7540864cf5d294d7b881eb886a3804f6d05 Thanks @ematipico! - Adds new helper functions for adapter developers.

    • Astro.clientAddress can now be passed directly to the app.render() method.
    const response = await app.render(request, { clientAddress: '012.123.23.3' });
    
    • Helper functions for converting Node.js HTTP request and response objects to web-compatible Request and Response objects are now provided as static methods on the NodeApp class.
    http.createServer((nodeReq, nodeRes) => {
      const request: Request = NodeApp.createRequest(nodeReq);
      const response = await app.render(request);
      await NodeApp.writeResponse(response, nodeRes);
    });
    
    • Cookies added via Astro.cookies.set() can now be automatically added to the Response object by passing the addCookieHeader option to app.render().
    -const response = await app.render(request)
    -const setCookieHeaders: Array<string> = Array.from(app.setCookieHeaders(webResponse));
    
    -if (setCookieHeaders.length) {
    -    for (const setCookieHeader of setCookieHeaders) {
    -        headers.append('set-cookie', setCookieHeader);
    -    }
    -}
    +const response = await app.render(request, { addCookieHeader: true })
    
  • #9638 f1a61268061b8834f39a9b38bca043ae41caed04 Thanks @ematipico! - Adds a new i18n.routing config option redirectToDefaultLocale to disable automatic redirects of the root URL (/) to the default locale when prefixDefaultLocale: true is set.

    In projects where every route, including the default locale, is prefixed with /[locale]/ path, this property allows you to control whether or not src/pages/index.astro should automatically redirect your site visitors from / to /[defaultLocale].

    You can now opt out of this automatic redirection by setting redirectToDefaultLocale: false:

    // astro.config.mjs
    export default defineConfig({
      i18n: {
        defaultLocale: 'en',
        locales: ['en', 'fr'],
        routing: {
          prefixDefaultLocale: true,
          redirectToDefaultLocale: false,
        },
      },
    });
    
  • #9671 8521ff77fbf7e867701cc30d18253856914dbd1b Thanks @bholmesdev! - Removes the requirement for non-content files and assets inside content collections to be prefixed with an underscore. For files with extensions like .astro or .css, you can now remove underscores without seeing a warning in the terminal.

    src/content/blog/
    post.mdx
    - _styles.css
    - _Component.astro
    + styles.css
    + Component.astro
    

    Continue to use underscores in your content collections to exclude individual content files, such as drafts, from the build output.

  • #9567 3a4d5ec8001ebf95c917fdc0d186d29650533d93 Thanks @OliverSpeir! - Improves the a11y-missing-content rule and error message for audit feature of dev-overlay. This also fixes an error where this check was falsely reporting accessibility errors.

  • #9643 e9a72d9a91a3741566866bcaab11172cb0dc7d31 Thanks @blackmann! - Adds a new markdown.shikiConfig.transformers config option. You can use this option to transform the Shikiji hast (AST format of the generated HTML) to customize the final HTML. Also updates Shikiji to the latest stable version.

    See Shikiji's documentation for more details about creating your own custom transformers, and a list of common transformers you can add directly to your project.

  • #9644 a5f1682347e602330246129d4666a9227374c832 Thanks @rossrobino! - Adds an experimental flag clientPrerender to prerender your prefetched pages on the client with the Speculation Rules API.

    // astro.config.mjs
    {
      prefetch: {
        prefetchAll: true,
        defaultStrategy: 'viewport',
      },
      experimental: {
        clientPrerender: true,
      },
    }
    

    Enabling this feature overrides the default prefetch behavior globally to prerender links on the client according to your prefetch configuration. Instead of appending a <link> tag to the head of the document or fetching the page with JavaScript, a <script> tag will be appended with the corresponding speculation rules.

    Client side prerendering requires browser support. If the Speculation Rules API is not supported, prefetch will fallback to the supported strategy.

    See the Prefetch Guide for more prefetch options and usage.

  • #9439 fd17f4a40b83d14350dce691aeb79d87e8fcaf40 Thanks @Fryuni! - Adds an experimental flag globalRoutePriority to prioritize redirects and injected routes equally alongside file-based project routes, following the same route priority order rules for all routes.

    // astro.config.mjs
    export default defineConfig({
      experimental: {
        globalRoutePriority: true,
      },
    });
    

    Enabling this feature ensures that all routes in your project follow the same, predictable route priority order rules. In particular, this avoids an issue where redirects or injected routes (e.g. from an integration) would always take precedence over local route definitions, making it impossible to override some routes locally.

    The following table shows which route builds certain page URLs when file-based routes, injected routes, and redirects are combined as shown below:

    • File-based route: /blog/post/[pid]
    • File-based route: /[page]
    • Injected route: /blog/[...slug]
    • Redirect: /blog/tags/[tag] -> /[tag]
    • Redirect: /posts -> /blog

    URLs are handled by the following routes:

    Page Current Behavior Global Routing Priority Behavior
    /blog/tags/astro Injected route /blog/[...slug] Redirect to /tags/[tag]
    /blog/post/0 Injected route /blog/[...slug] File-based route /blog/post/[pid]
    /posts File-based route /[page] Redirect to /blog

    In the event of route collisions, where two routes of equal route priority attempt to build the same URL, Astro will log a warning identifying the conflicting routes.

Patch Changes

4.1.3

Patch Changes

4.1.2

Patch Changes

4.1.1

Patch Changes

4.1.0

Minor Changes

  • #9513 e44f6acf99195a3f29b8390fd9b2c06410551b74 Thanks @wtto00! - Adds a 'load' prefetch strategy to prefetch links on page load

  • #9377 fe719e27a84c09e46b515252690678c174a25759 Thanks @bluwy! - Adds "Missing ARIA roles check" and "Unsupported ARIA roles check" audit rules for the dev toolbar

  • #9573 2a8b9c56b9c6918531c57ec38b89474571331aee Thanks @bluwy! - Allows passing a string to --open and server.open to open a specific URL on startup in development

  • #9544 b8a6fa8917ff7babd35dafb3d3dcd9a58cee836d Thanks @bluwy! - Adds a helpful error for static sites when you use the astro preview command if you have not previously run astro build.

  • #9546 08402ad5846c73b6887e74ed4575fd71a3e3c73d Thanks @bluwy! - Adds an option for the Sharp image service to allow large images to be processed. Set limitInputPixels: false to bypass the default image size limit:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      image: {
        service: {
          entrypoint: 'astro/assets/services/sharp',
          config: {
            limitInputPixels: false,
          },
        },
      },
    });
    
  • #9596 fbc26976533bbcf2de9d6dba1aa3ea3dc6ce0853 Thanks @Princesseuh! - Adds the ability to set a rootMargin setting when using the client:visible directive. This allows a component to be hydrated when it is near the viewport, rather than hydrated when it has entered the viewport.

    <!-- Load component when it's within 200px away from entering the viewport -->
    <Component client:visible={{ rootMargin: '200px' }} />
    
  • #9063 f33fe3190b482a42ebc68cc5275fd7f2c49102e6 Thanks @alex-sherwin! - Cookie encoding / decoding can now be customized

    Adds new encode and decode functions to allow customizing how cookies are encoded and decoded. For example, you can bypass the default encoding via encodeURIComponent when adding a URL as part of a cookie:

    ---
    import { encodeCookieValue } from './cookies';
    Astro.cookies.set('url', Astro.url.toString(), {
      // Override the default encoding so that URI components are not encoded
      encode: (value) => encodeCookieValue(value),
    });
    ---
    

    Later, you can decode the URL in the same way:

    ---
    import { decodeCookieValue } from './cookies';
    const url = Astro.cookies.get('url', {
      decode: (value) => decodeCookieValue(value),
    });
    ---
    

Patch Changes

4.0.9

Patch Changes

4.0.8

Patch Changes

4.0.7

Patch Changes

4.0.6

Patch Changes

4.0.5

Patch Changes

4.0.4

Patch Changes

  • #9380 ea0918259 Thanks @ematipico! - Correctly handle the rendering of i18n routes when output: "hybrid" is set

  • #9374 65ddb0271 Thanks @bluwy! - Fixes an issue where prerendered route paths that end with .mjs were removed from the final build

  • #9375 26f7023d6 Thanks @bluwy! - Prettifies generated route names injected by integrations

  • #9387 a7c75b333 Thanks @natemoo-re! - Fixes an edge case with astro add that could install a prerelease instead of a stable release version.

    Prior to this change astro add svelte installs svelte@5.0.0-next.22

    After this change astro add svelte installs svelte@4.2.8

  • Updated dependencies [270c6cc27]:

    • @astrojs/markdown-remark@4.0.1

4.0.3

Patch Changes

4.0.2

Patch Changes

  • #9331 cfb20550d Thanks @natemoo-re! - Updates an internal dependency (vitefu) to avoid a common peerDependency warning

  • #9327 3878a91be Thanks @doseofted! - Fixes an edge case for <form method="dialog"> when using View Transitions. Forms with method="dialog" no longer require an additional data-astro-reload attribute.

4.0.1

Patch Changes

  • #9315 631e5d01b Thanks @ematipico! - Fixes an issue where logs that weren't grouped together by route when building the app.

4.0.0

Major Changes

  • #9138 abf601233 Thanks @bluwy! - Updates the unified, remark, and rehype dependencies to latest. Make sure to update your custom remark and rehype plugins as well to be compatible with the latest versions.

    Potentially breaking change: The default value of markdown.remarkRehype.footnoteBackLabel is changed from "Back to content" to "Back to reference 1". See the mdast-util-to-hast commit for more information.

  • #9181 cdabf6ef0 Thanks @bluwy! - Removes support for returning simple objects from endpoints (deprecated since Astro 3.0). You should return a Response instead.

    ResponseWithEncoding is also removed. You can refactor the code to return a response with an array buffer instead, which is encoding agnostic.

    The types for middlewares have also been revised. To type a middleware function, you should now use MiddlewareHandler instead of MiddlewareResponseHandler. If you used defineMiddleware() to type the function, no changes are needed.

  • #9263 3cbd8ea75 Thanks @bluwy! - Removes additional deprecated APIs:

    • The Astro preview server now returns a 404 status instead of a 301 redirect when requesting assets from the public directory without a base.
    • Removes special handling when referencing the astro/client-image type. You should use the astro/client type instead.
    • Removes deprecated built-in rss support in getStaticPaths. You should use @astrojs/rss instead.
    • Removes deprecated Astro.request.params support. You should use Astro.params instead.
  • #9271 47604bd5b Thanks @matthewp! - Renames Dev Overlay to Dev Toolbar

    The previously named experimental Dev Overlay is now known as the Astro Dev Toolbar. Overlay plugins have been renamed as Toolbar Apps. All APIs have been updated to reflect this name change.

    To not break existing APIs, aliases for the Toolbar-based names have been created. The previous API names will continue to function but will be deprecated in the future. All documentation has been updated to reflect Toolbar-based names.

  • #9122 1c48ed286 Thanks @bluwy! - Adds Vite 5 support. There are no breaking changes from Astro. Check the Vite migration guide for details of the breaking changes from Vite instead.

  • #9225 c421a3d17 Thanks @natemoo-re! - Removes the opt-in handleForms property for <ViewTransitions />. Form submissions are now handled by default and this property is no longer necessary. This default behavior can be disabled by setting data-astro-reload on relevant <form /> elements.

  • #9196 37697a2c5 Thanks @bluwy! - Removes support for Shiki custom language's path property. The language JSON file should be imported and passed to the option instead.

    // astro.config.js
    + import customLang from './custom.tmLanguage.json'
    
    export default defineConfig({
      markdown: {
        shikiConfig: {
          langs: [
    -       { path: './custom.tmLanguage.json' },
    +       customLang,
          ],
        },
      },
    })
    
  • #9199 49aa215a0 Thanks @lilnasy! - This change only affects maintainers of third-party adapters. In the Integration API, the app.render() method of the App class has been simplified.

    Instead of two optional arguments, it now takes a single optional argument that is an object with two optional properties: routeData and locals.

     app.render(request)
    
    - app.render(request, routeData)
    + app.render(request, { routeData })
    
    - app.render(request, routeData, locals)
    + app.render(request, { routeData, locals })
    
    - app.render(request, undefined, locals)
    + app.render(request, { locals })
    

    The current signature is deprecated but will continue to function until next major version.

  • #9212 c0383ea0c Thanks @alexanderniebuhr! - Removes deprecated app.match() option, matchNotFound

  • #9168 153a5abb9 Thanks @bluwy! - Removes deprecated features from Astro 3.0

    • Adapters are now required to pass supportedAstroFeatures to specify a list of features they support.
    • The build.split and build.excludeMiddleware options are removed. Use functionPerRoute and edgeMiddleware from adapters instead.
    • The markdown.drafts option and draft feature is removed. Use content collections instead.
    • Lowercase endpoint names are no longer supported. Use uppercase endpoint names instead.
    • getHeaders() exported from markdown files is removed. Use getHeadings() instead.

Minor Changes

  • #9105 6201bbe96 Thanks @FredKSchott! - Update CLI logging experience

  • #9200 b4b851f5a Thanks @ematipico! - Adds a new way to configure the i18n.locales array.

    Developers can now assign a custom URL path prefix that can span multiple language codes:

    // astro.config.mjs
    export default defineConfig({
      experimental: {
        i18n: {
          defaultLocale: 'english',
          locales: ['de', { path: 'english', codes: ['en', 'en-US'] }, 'fr'],
        },
      },
    });
    

    With the above configuration, the URL prefix of the default locale will be /english/. When computing Astro.preferredLocale, Astro will use the codes.

  • #9115 3b77889b4 Thanks @natemoo-re! - Adds the astro preferences command to manage user preferences. User preferences are specific to individual Astro users, unlike the astro.config.mjs file which changes behavior for everyone working on a project.

    User preferences are scoped to the current project by default, stored in a local .astro/settings.json file. Using the --global flag, user preferences can also be applied to every Astro project on the current machine. Global user preferences are stored in an operating system-specific location.

    # Disable the dev overlay for the current user in the current project
    npm run astro preferences disable devOverlay
    # Disable the dev overlay for the current user in all Astro projects on this machine
    npm run astro preferences --global disable devOverlay
    
    # Check if the dev overlay is enabled for the current user
    npm run astro preferences list devOverlay
    
  • #9139 459b26436 Thanks @bluwy! - Reworks Vite's logger to use Astro's logger to correctly log HMR messages

  • #9279 6a9669b81 Thanks @martrapp! - Improves consistency between navigations with and without <ViewTransitions>. See #9279 for more details.

  • #9161 bd0c2e9ae Thanks @bluwy! - Renames the entryPoint property of the injectRoute integrations API to entrypoint for consistency. A warning will be shown prompting you to update your code when using the old name.

  • #9129 8bfc20511 Thanks @FredKSchott! - Update error log formatting

Patch Changes

  • #9118 000e8f465 Thanks @Princesseuh! - Redesign Dev Overlay main screen to show more information, such as the coolest integrations, your current Astro version and more.

  • #9118 000e8f465 Thanks @Princesseuh! - Fixes an issue where links with the same pathname as the current page, but different search params, were not prefetched.

  • #9275 0968cb1a3 Thanks @lilnasy! - Fixes an issue where html annotations relevant only to the dev server were included in the production build.

  • #9252 7b74ec4ba Thanks @ematipico! - Consistently emit fallback routes in the correct folders, and emit routes that consider trailingSlash

  • #9222 279e3c1b3 Thanks @matthewp! - Ensure the dev-overlay-window is anchored to the bottom

  • #9292 5428b3da0 Thanks @natemoo-re! - Improves display for astro preferences list command

  • #9235 9c2342c32 Thanks @Princesseuh! - Fix SVG icons not showing properly in the extended dropdown menu of the dev overlay

  • #9218 f4401c8c1 Thanks @matthewp! - Improve high contrast mode with the Dev Overlay

  • #9254 b750a161e Thanks @matthewp! - Improve highlight/tooltip positioning when in fixed positions

  • #9230 60cfa49e4 Thanks @FredKSchott! - Update the look and feel of the dev overlay

  • #9248 43ddb5217 Thanks @martrapp! - Adds properties of the submit button (name, value) to the form data of a view transition

  • #9170 8a228fce0 Thanks @natemoo-re! - Adds new accessibility audits to the Dev Toolbar's built-in Audits app.

    The audits Astro performs are non-exhaustive and only capable of detecting a handful of common accessibility issues. Please take care to perform a thorough, manual audit of your site to ensure compliance with the Web Content Accessibility Guidelines (WCAG) international standard before publishing your site.

    🧡 Huge thanks to the Svelte team for providing the basis of these accessibility audits!

  • #9149 0fe3a7ed5 Thanks @bluwy! - Removes vendored Vite's importMeta.d.ts file in favour of Vite 5's new vite/types/import-meta.d.ts export

  • #9295 3d2dbb0e5 Thanks @matthewp! - Remove aria-query package

    This is another CJS-only package that breaks usage.

  • #9274 feaba2c7f Thanks @TheOtterlord! - Fix routing prefixes when prefixDefaultLocale is true

  • #9273 9887f2412 Thanks @alexanderniebuhr! - Exports type for Dev Toolbar App under correct name

  • #9150 710be505c Thanks @bluwy! - Refactors virtual modules exports. This should not break your project unless you import Astro's internal modules, including:

    • astro/middleware/namespace
    • astro/transitions
    • astro/transitions/router
    • astro/transitions/events
    • astro/transitions/types
    • astro/prefetch
    • astro/i18n
  • #9227 4b8a42406 Thanks @matthewp! - Ensure overlay x-ray z-index is higher than the island

  • #9255 9ea3e0b94 Thanks @matthewp! - Adds instructions on how to hide the dev overlay

  • #9293 cf5fa4376 Thanks @matthewp! - Removes the 'a11y-role-has-required-aria-props' audit rule

    This audit rule depends on a CommonJS module. To prevent blocking the 4.0 release the rule is being removed temporarily.

  • #9214 4fe523b00 Thanks @Princesseuh! - Fixes a number of small user experience bugs with the dev overlay

  • #9013 ff8eadb95 Thanks @bayssmekanique! - Returns the updated config in the integration astro:config:setup hook's updateConfig() API

  • Updated dependencies [abf601233, addb57c8e, c7953645e]:

    • @astrojs/markdown-remark@4.0.0

4.0.0-beta.7

Patch Changes

  • #9295 3d2dbb0e5 Thanks @matthewp! - Remove aria-query package

    This is another CJS-only package that breaks usage.

4.0.0-beta.6

Patch Changes

  • #9275 0968cb1a3 Thanks @lilnasy! - Fixes an issue where html annotations relevant only to the dev server were included in the production build.

  • #9292 5428b3da0 Thanks @natemoo-re! - Improves display for astro preferences list command

  • #9293 cf5fa4376 Thanks @matthewp! - Removes the 'a11y-role-has-required-aria-props' audit rule

    This audit rule depends on a CommonJS module. To prevent blocking the 4.0 release the rule is being removed temporarily.

4.0.0-beta.5

Minor Changes

  • #9279 6a9669b81 Thanks @martrapp! - Improves consistency between navigations with and without <ViewTransitions>. See #9279 for more details.

Patch Changes

4.0.0-beta.4

Major Changes

  • #9271 47604bd5b Thanks @matthewp! - Renames Dev Overlay to Dev Toolbar

    The previously named experimental Dev Overlay is now known as the Astro Dev Toolbar. Plugins have been renamed as Toolbar Apps. This updates our references to reflect.

    To not break existing APIs, aliases for the Toolbar-based names have been created. The previous API names will continue to function but will be deprecated in the future. All documentation has been updated to reflect Toolbar-based names.

4.0.0-beta.3

Major Changes

  • #9263 3cbd8ea75 Thanks @bluwy! - Removes additional deprecated APIs:

    • The Astro preview server now returns a 404 status instead of a 301 redirect when requesting assets from the public directory without a base.
    • Removes special handling when referencing the astro/client-image type. You should use the astro/client type instead.
    • Removes deprecated built-in rss support in getStaticPaths. You should use @astrojs/rss instead.
    • Removes deprecated Astro.request.params support. You should use Astro.params instead.

Minor Changes

  • #9200 b4b851f5a Thanks @ematipico! - Adds a new way to configure the i18n.locales array.

    Developers can now assign a custom URL path prefix that can span multiple language codes:

    // astro.config.mjs
    export default defineConfig({
      experimental: {
        i18n: {
          defaultLocale: 'english',
          locales: ['de', { path: 'english', codes: ['en', 'en-US'] }, 'fr'],
          routingStrategy: 'prefix-always',
        },
      },
    });
    

    With the above configuration, the URL prefix of the default locale will be /english/. When computing Astro.preferredLocale, Astro will use the codes.

  • #9139 459b26436 Thanks @bluwy! - Reworks Vite's logger to use Astro's logger to correctly log HMR messages

Patch Changes

4.0.0-beta.2

Major Changes

  • #9225 c421a3d17 Thanks @natemoo-re! - Removes the opt-in handleForms property for <ViewTransitions />. Form submissions are now handled by default and can be disabled by setting data-astro-reload on relevant <form /> elements.

  • #9199 49aa215a0 Thanks @lilnasy! - This change only affects maintainers of third-party adapters. In the Integration API, the app.render() method of the App class has been simplified.

    Instead of two optional arguments, it now takes a single optional argument that is an object with two optional properties: routeData and locals.

     app.render(request)
    
    - app.render(request, routeData)
    + app.render(request, { routeData })
    
    - app.render(request, routeData, locals)
    + app.render(request, { routeData, locals })
    
    - app.render(request, undefined, locals)
    + app.render(request, { locals })
    

    The current signature is deprecated but will continue to function until next major version.

  • #9212 c0383ea0c Thanks @alexanderniebuhr! - Removes deprecated app.match() option, matchNotFound

Minor Changes

  • #9115 3b77889b4 Thanks @natemoo-re! - Adds the astro preferences command to manage user preferences. User preferences are specific to individual Astro users, unlike the astro.config.mjs file which changes behavior for everyone working on a project.

    User preferences are scoped to the current project by default, stored in a local .astro/settings.json file. Using the --global flag, user preferences can also be applied to every Astro project on the current machine. Global user preferences are stored in an operating system-specific location.

    # Disable the dev overlay for the current user in the current project
    npm run astro preferences disable devOverlay
    # Disable the dev overlay for the current user in all Astro projects on this machine
    npm run astro preferences --global disable devOverlay
    
    # Check if the dev overlay is enabled for the current user
    npm run astro preferences list devOverlay
    
  • #9129 8bfc20511 Thanks @FredKSchott! - Update error log formatting

Patch Changes

4.0.0-beta.1

Patch Changes

  • #9118 000e8f465 Thanks @Princesseuh! - Redesign Dev Overlay main screen to show more information, such as the coolest integrations, your current Astro version and more.

  • #9118 000e8f465 Thanks @Princesseuh! - Fixes an issue where links with the same pathname as the current page, but different search params, were not prefetched.

4.0.0-beta.0

Major Changes

  • #9138 abf601233 Thanks @bluwy! - Updates the unified, remark, and rehype dependencies to latest. Make sure to update your custom remark and rehype plugins as well to be compatible with the latest versions.

    Potentially breaking change: The default value of markdown.remarkRehype.footnoteBackLabel is changed from "Back to content" to "Back to reference 1". See the mdast-util-to-hast commit for more information.

  • #9181 cdabf6ef0 Thanks @bluwy! - Removes support for returning simple objects from endpoints (deprecated since Astro 3.0). You should return a Response instead.

    ResponseWithEncoding is also removed. You can refactor the code to return a response with an array buffer instead, which is encoding agnostic.

    The types for middlewares have also been revised. To type a middleware function, you should now use MiddlewareHandler instead of MiddlewareResponseHandler. If you used defineMiddleware() to type the function, no changes are needed.

  • #9122 1c48ed286 Thanks @bluwy! - Adds Vite 5 support. There are no breaking changes from Astro. Check the Vite migration guide for details of the breaking changes from Vite instead.

  • #9196 37697a2c5 Thanks @bluwy! - Removes support for Shiki custom language's path property. The language JSON file should be imported and passed to the option instead.

    // astro.config.js
    + import customLang from './custom.tmLanguage.json'
    
    export default defineConfig({
      markdown: {
        shikiConfig: {
          langs: [
    -       { path: './custom.tmLanguage.json' },
    +       customLang,
          ],
        },
      },
    })
    
  • #9168 153a5abb9 Thanks @bluwy! - Removes deprecated features from Astro 3.0

    • Adapters are now required to pass supportedAstroFeatures to specify a list of features they support.
    • The build.split and build.excludeMiddleware options are removed. Use functionPerRoute and edgeMiddleware from adapters instead.
    • The markdown.drafts option and draft feature is removed. Use content collections instead.
    • Lowercase endpoint names are no longer supported. Use uppercase endpoint names instead.
    • getHeaders() exported from markdown files is removed. Use getHeadings() instead.

Minor Changes

  • #9105 6201bbe96 Thanks @FredKSchott! - Update CLI logging experience

  • #9161 bd0c2e9ae Thanks @bluwy! - Renames the entryPoint property of the injectRoute integrations API to entrypoint for consistency. A warning will be shown prompting you to update your code when using the old name.

Patch Changes

  • #9149 0fe3a7ed5 Thanks @bluwy! - Removes vendored Vite's importMeta.d.ts file in favour of Vite 5's new vite/types/import-meta.d.ts export

  • #9150 710be505c Thanks @bluwy! - Refactors virtual modules exports. This should not break your project unless you import Astro's internal modules, including:

    • astro/middleware/namespace
    • astro/transitions
    • astro/transitions/router
    • astro/transitions/events
    • astro/transitions/types
    • astro/prefetch
    • astro/i18n
  • Updated dependencies [abf601233, addb57c8e, c7953645e]:

    • @astrojs/markdown-remark@4.0.0-beta.0

3.6.4

Patch Changes

  • #9226 8f8a40e93 Thanks @outofambit! - Fix i18n fallback routing with routing strategy of always-prefix

  • #9179 3f28336d9 Thanks @lilnasy! - Fixes an issue where the presence of a slot in a page led to an error.

  • #9219 067a65f5b Thanks @natemoo-re! - Fix edge case where <style> updates inside of .astro files would ocassionally fail to update without reloading the page.

  • #9236 27d3e86e4 Thanks @ematipico! - The configuration i18n.routingStrategy has been replaced with an object called routing.

    export default defineConfig({
      experimental: {
          i18n: {
    -          routingStrategy: "prefix-always",
    +          routing: {
    +              prefixDefaultLocale: true,
    +          }
          }
      }
    })
    
    export default defineConfig({
      experimental: {
          i18n: {
    -          routingStrategy: "prefix-other-locales",
    +          routing: {
    +              prefixDefaultLocale: false,
    +          }
          }
      }
    })
    

3.6.3

Patch Changes

3.6.2

Patch Changes

  • #9189 d90714fc3 Thanks @SpencerWhitehead7! - Fixes an issue where links with the same pathname as the current page, but different search params, were not prefetched.

3.6.4

Patch Changes

  • #9226 8f8a40e93 Thanks @outofambit! - Fix i18n fallback routing with routing strategy of always-prefix

  • #9179 3f28336d9 Thanks @lilnasy! - Fixes an issue where the presence of a slot in a page led to an error.

  • #9219 067a65f5b Thanks @natemoo-re! - Fix edge case where <style> updates inside of .astro files would ocassionally fail to update without reloading the page.

  • #9236 27d3e86e4 Thanks @ematipico! - The configuration i18n.routingStrategy has been replaced with an object called routing.

    export default defineConfig({
      experimental: {
          i18n: {
    -          routingStrategy: "prefix-always",
    +          routing: {
    +              prefixDefaultLocale: true,
    +          }
          }
      }
    })
    
    export default defineConfig({
      experimental: {
          i18n: {
    -          routingStrategy: "prefix-other-locales",
    +          routing: {
    +              prefixDefaultLocale: false,
    +          }
          }
      }
    })
    

3.6.3

Patch Changes

3.6.2

Patch Changes

  • #9189 d90714fc3 Thanks @SpencerWhitehead7! - Fixes an issue where links with the same pathname as the current page, but different search params, were not prefetched.

3.6.1

Patch Changes

  • #9173 04fdc1c61 Thanks @lilnasy! - Fixes an issue where having a middleware prevented the SSR app from being deployed on Netlify.

  • #9186 607542c7c Thanks @martrapp! - Fixes a view transition issue on webKit browsers that prevented scrolling to #fragments

3.6.0

Minor Changes

  • #9090 c87223c21 Thanks @martrapp! - Take full control over the behavior of view transitions!

    Three new events now complement the existing astro:after-swap and astro:page-load events:

    'astro:before-preparation'; // Control how the DOM and other resources of the target page are loaded
    'astro:after-preparation'; // Last changes before taking off? Remove that loading indicator? Here you go!
    'astro:before-swap'; // Control how the DOM is updated to match the new page
    

    The astro:before-* events allow you to change properties and strategies of the view transition implementation. The astro:after-* events are notifications that a phase is complete. Head over to docs to see the full view transitions lifecycle including these new events!

  • #9092 0ea4bd47e Thanks @smitbarmase! - Changes the fallback prefetch behavior on slow connections and when data saver mode is enabled. Instead of disabling prefetch entirely, the tap strategy will be used.

  • #9166 cba6cf32d Thanks @matthewp! - The Picture component is no longer experimental

    The <Picture /> component, part of astro:assets, has exited experimental status and is now recommended for use. There are no code changes to the component, and no upgrade to your project is necessary.

    This is only a change in documentation/recommendation. If you were waiting to use the <Picture /> component until it had exited the experimental stage, wait no more!

  • #9092 0ea4bd47e Thanks @smitbarmase! - Adds a ignoreSlowConnection option to the prefetch() API to prefetch even on data saver mode or slow connection.

3.5.7

Patch Changes

3.5.6

Patch Changes

3.5.5

Patch Changes

  • #9091 536c6c9fd Thanks @ematipico! - The routingStrategy prefix-always should not force its logic to endpoints. This fixes some regression with astro:assets and @astrojs/rss.

  • #9102 60e8210b0 Thanks @Princesseuh! - In the dev overlay, when there's too many plugins enabled at once, some of the plugins will now be hidden in a separate sub menu to avoid the bar becoming too long

3.5.4

Patch Changes

3.5.3

Patch Changes

3.5.2

Patch Changes

3.5.1

Patch Changes

3.5.0

Minor Changes

  • #8869 f5bdfa272 Thanks @matthewp! - ## Integration Hooks to add Middleware

    It's now possible in Astro for an integration to add middleware on behalf of the user. Previously when a third party wanted to provide middleware, the user would need to create a src/middleware.ts file themselves. Now, adding third-party middleware is as easy as adding a new integration.

    For integration authors, there is a new addMiddleware function in the astro:config:setup hook. This function allows you to specify a middleware module and the order in which it should be applied:

    // my-package/middleware.js
    import { defineMiddleware } from 'astro:middleware';
    
    export const onRequest = defineMiddleware(async (context, next) => {
      const response = await next();
    
      if (response.headers.get('content-type') === 'text/html') {
        let html = await response.text();
        html = minify(html);
        return new Response(html, {
          status: response.status,
          headers: response.headers,
        });
      }
    
      return response;
    });
    

    You can now add your integration's middleware and specify that it runs either before or after the application's own defined middleware (defined in src/middleware.{js,ts})

    // my-package/integration.js
    export function myIntegration() {
      return {
        name: 'my-integration',
        hooks: {
          'astro:config:setup': ({ addMiddleware }) => {
            addMiddleware({
              entrypoint: 'my-package/middleware',
              order: 'pre',
            });
          },
        },
      };
    }
    
  • #8854 3e1239e42 Thanks @natemoo-re! - Provides a new, experimental build cache for Content Collections as part of the Incremental Build RFC. This includes multiple refactors to Astro's build process to optimize how Content Collections are handled, which should provide significant performance improvements for users with many collections.

    Users building a static site can opt-in to preview the new build cache by adding the following flag to your Astro config:

    // astro.config.mjs
    export default {
      experimental: {
        contentCollectionCache: true,
      },
    };
    

    When this experimental feature is enabled, the files generated from your content collections will be stored in the cacheDir (by default, node_modules/.astro) and reused between builds. Most CI environments automatically restore files in node_modules/ by default.

    In our internal testing on the real world Astro Docs project, this feature reduces the bundling step of astro build from 133.20s to 10.46s, about 92% faster. The end-to-end astro build process used to take 4min 58s and now takes just over 1min for a total reduction of 80%.

    If you run into any issues with this experimental feature, please let us know!

    You can always bypass the cache for a single build by passing the --force flag to astro build.

    astro build --force
    
  • #8963 fda3a0213 Thanks @matthewp! - Form support in View Transitions router

    The <ViewTransitions /> router can now handle form submissions, allowing the same animated transitions and stateful UI retention on form posts that are already available on <a> links. With this addition, your Astro project can have animations in all of these scenarios:

    • Clicking links between pages.
    • Making stateful changes in forms (e.g. updating site preferences).
    • Manually triggering navigation via the navigate() API.

    This feature is opt-in for semver reasons and can be enabled by adding the handleForms prop to the ` component:

    ---
    // src/layouts/MainLayout.astro
    import { ViewTransitions } from 'astro:transitions';
    ---
    
    <html>
      <head>
        <!-- ... -->
        <ViewTransitions handleForms />
      </head>
      <body>
        <!-- ... -->
      </body>
    </html>
    

    Just as with links, if you don't want the routing handling a form submission, you can opt out on a per-form basis with the data-astro-reload property:

    ---
    // src/components/Contact.astro
    ---
    
    <form class="contact-form" action="/request" method="post" data-astro-reload>
      <!-- ...-->
    </form>
    

    Form support works on post method="get" and method="post" forms.

  • #8954 f0031b0a3 Thanks @Princesseuh! - Updates the Image Services API to now delete original images from the final build that are not used outside of the optimization pipeline. For users with a large number of these images (e.g. thumbnails), this should reduce storage consumption and deployment times.

  • #8984 26b1484e8 Thanks @Princesseuh! - Adds a new property propertiesToHash to the Image Services API to allow specifying which properties of getImage() / <Image /> / <Picture /> should be used for hashing the result files when doing local transformations. For most services, this will include properties such as src, width or quality that directly changes the content of the generated image.

  • #9010 100b61ab5 Thanks @jasikpark! - The <Picture /> component will now use jpg and jpeg respectively as fallback formats when the original image is in those formats.

  • #8974 143bacf39 Thanks @ematipico! - Experimental support for i18n routing.

    Astro's experimental i18n routing API allows you to add your multilingual content with support for configuring a default language, computing relative page URLs, and accepting preferred languages provided by your visitor's browser. You can also specify fallback languages on a per-language basis so that your visitors can always be directed to existing content on your site.

    Enable the experimental routing option by adding an i18n object to your Astro configuration with a default location and a list of all languages to support:

    // astro.config.mjs
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      experimental: {
        i18n: {
          defaultLocale: 'en',
          locales: ['en', 'es', 'pt-br'],
        },
      },
    });
    

    Organize your content folders by locale depending on your i18n.routingStrategy, and Astro will handle generating your routes and showing your preferred URLs to your visitors.

    ├── src
    │   ├── pages
    │   │   ├── about.astro
    │   │   ├── index.astro
    │   │   ├── es
    │   │   │   ├── about.astro
    │   │   │   ├── index.astro
    │   │   ├── pt-br
    │   │   │   ├── about.astro
    │   │   │   ├── index.astro
    

    Compute relative URLs for your links with getRelativeLocaleUrl from the new astro:i18n module:

    ---
    import { getRelativeLocaleUrl } from 'astro:i18n';
    const aboutUrl = getRelativeLocaleUrl('pt-br', 'about');
    ---
    
    <p>Learn more <a href={aboutURL}>About</a> this site!</p>
    

    Enabling i18n routing also provides two new properties for browser language detection: Astro.preferredLocale and Astro.preferredLocaleList. These combine the browser's Accept-Langauge header, and your site's list of supported languages and can be used to automatically respect your visitor's preferred languages.

    Read more about Astro's experimental i18n routing in our documentation.

  • #8951 38e21d127 Thanks @bluwy! - Prefetching is now supported in core

    You can enable prefetching for your site with the prefetch: true config. It is enabled by default when using View Transitions and can also be used to configure the prefetch behaviour used by View Transitions.

    You can enable prefetching by setting prefetch:true in your Astro config:

    // astro.config.js
    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
      prefetch: true,
    });
    

    This replaces the @astrojs/prefetch integration, which is now deprecated and will eventually be removed. Visit the Prefetch guide for more information.

  • #8903 c5010aad3 Thanks @horo-fox! - Adds experimental support for multiple shiki themes with the new markdown.shikiConfig.experimentalThemes option.

Patch Changes

  • #9016 1ecc9aa32 Thanks @Princesseuh! - Add ability to "Click to go editor" on auditted elements in the dev overlay

  • #9029 29b83e9e4 Thanks @Princesseuh! - Use UInt8Array instead of Buffer for both the input and return values of the transform() hook of the Image Service API to ensure compatibility with non-Node runtimes.

    This change is unlikely to affect you, but if you were previously relying on the return value being a Buffer, you may convert an UInt8Array to a Buffer using Buffer.from(your_array).

  • Updated dependencies [c5010aad3]:

    • @astrojs/markdown-remark@3.4.0

3.4.4

Patch Changes

  • #9000 35739d01e Thanks @martrapp! - Fixes an error in dev mode on Safari where view transitions prevented navigating to pages with client:only components

  • #9014 d979b8f0a Thanks @Princesseuh! - Add animations, shadows and general styling tweaks to the Dev Overlay to better match the intended design.

  • #8996 3988bbcc9 Thanks @bluwy! - Adds compatibility for shiki languages with the path property

  • #8986 910eb00fe Thanks @Princesseuh! - Fix sizes attribute not being present on source elements when using it on the Picture component

3.4.3

Patch Changes

3.4.2

Patch Changes

3.4.1

Patch Changes

3.4.0

Minor Changes

  • #8755 fe4079f05 Thanks @matthewp! - Page Partials

    A page component can now be identified as a partial page, which will render its HTML content without including a <! DOCTYPE html> declaration nor any <head> content.

    A rendering library, like htmx or Stimulus or even just jQuery can access partial content on the client to dynamically update only parts of a page.

    Pages marked as partials do not have a doctype or any head content included in the rendered result. You can mark any page as a partial by setting this option:

    ---
    export const partial = true;
    ---
    
    <li>This is a single list item.</li>
    

    Other valid page files that can export a value (e.g. .mdx) can also be marked as partials.

    Read more about Astro page partials in our documentation.

  • #8821 4740d761a Thanks @Princesseuh! - Improved image optimization performance

    Astro will now generate optimized images concurrently at build time, which can significantly speed up build times for sites with many images. Additionally, Astro will now reuse the same buffer for all variants of an image. This should improve performance for websites with many variants of the same image, especially when using remote images.

    No code changes are required to take advantage of these improvements.

  • #8757 e99586787 Thanks @Princesseuh! - Dev Overlay (experimental)

    Provides a new dev overlay for your browser preview that allows you to inspect your page islands, see helpful audits on performance and accessibility, and more. A Dev Overlay Plugin API is also included to allow you to add new features and third-party integrations to it.

    You can enable access to the dev overlay and its API by adding the following flag to your Astro config:

    // astro.config.mjs
    export default {
      experimental: {
        devOverlay: true,
      },
    };
    

    Read the Dev Overlay Plugin API documentation for information about building your own plugins to integrate with Astro's dev overlay.

  • #8880 8c3d4a859 Thanks @alexanderniebuhr! - Moves the logic for overriding the image service out of core and into adapters. Also fixes a regression where a valid astro:assets image service configuration could be overridden.

3.3.4

Patch Changes

  • #8877 26b77b8fe Thanks @bluwy! - Fixes CSS modules ordering by rendering styles before links

  • Updated dependencies [341ef6578]:

    • @astrojs/telemetry@3.0.4

3.3.3

Patch Changes

3.3.2

Patch Changes

3.3.1

Patch Changes

3.3.0

Minor Changes

  • #8808 2993055be Thanks @delucis! - Adds support for an --outDir CLI flag to astro build

  • #8502 c4270e476 Thanks @bluwy! - Updates the internal shiki syntax highlighter to shikiji, an ESM-focused alternative that simplifies bundling and maintenance.

    There are no new options and no changes to how you author code blocks and syntax highlighting.

    Potentially breaking change: While this refactor should be transparent for most projects, the transition to shikiji now produces a smaller HTML markup by attaching a fallback color style to the pre or code element, instead of to the line span directly. For example:

    Before:

    <code class="astro-code" style="background-color: #24292e">
      <pre>
        <span class="line" style="color: #e1e4e8">my code</span>
      </pre>
    </code>
    

    After:

    <code class="astro-code" style="background-color: #24292e; color: #e1e4e8">
      <pre>
        <span class="line">my code<span>
      </pre>
    </code>
    

    This does not affect the colors as the span will inherit the color from the parent, but if you're relying on a specific HTML markup, please check your site carefully after upgrading to verify the styles.

  • #8798 f369fa250 Thanks @Princesseuh! - Fixed tsconfig.json's new array format for extends not working. This was done by migrating Astro to use tsconfck instead of tsconfig-resolver to find and parse tsconfig.json files.

  • #8620 b2ae9ee0c Thanks @Princesseuh! - Adds experimental support for generating srcset attributes and a new <Picture /> component.

    srcset support

    Two new properties have been added to Image and getImage(): densities and widths.

    These properties can be used to generate a srcset attribute, either based on absolute widths in pixels (e.g. [300, 600, 900]) or pixel density descriptors (e.g. ["2x"] or [1.5, 2]).

    ---
    import { Image } from 'astro';
    import myImage from './my-image.jpg';
    ---
    
    <Image src={myImage} width={myImage.width / 2} densities={[1.5, 2]} alt="My cool image" />
    
    <img
      src="/_astro/my_image.hash.webp"
      srcset="/_astro/my_image.hash.webp 1.5x, /_astro/my_image.hash.webp 2x"
      alt="My cool image"
    />
    

    Picture component

    The experimental <Picture /> component can be used to generate a <picture> element with multiple <source> elements.

    The example below uses the format property to generate a <source> in each of the specified image formats:

    ---
    import { Picture } from 'astro:assets';
    import myImage from './my-image.jpg';
    ---
    
    <Picture src={myImage} formats={['avif', 'webp']} alt="My super image in multiple formats!" />
    

    The above code will generate the following HTML, and allow the browser to determine the best image to display:

    <picture>
      <source srcset="..." type="image/avif" />
      <source srcset="..." type="image/webp" />
      <img src="..." alt="My super image in multiple formats!" />
    </picture>
    

    The Picture component takes all the same props as the Image component, including the new densities and widths properties.

Patch Changes

  • #8771 bd5aa1cd3 Thanks @lilnasy! - Fixed an issue where the transitions router did not work within framework components.

  • #8800 391729686 Thanks @lilnasy! - Fixed an issue where attempting to assign a variable onto locals threw an error.

  • #8795 f999365b8 Thanks @bluwy! - Fix markdown page charset to be utf-8 by default (same as Astro 2)

  • #8810 0abff97fe Thanks @jacobthesheep! - Remove network-information-types package since TypeScript supports Network Information API natively.

  • #8813 3bef32f81 Thanks @martrapp! - Save and restore focus for persisted input elements during view transitions

  • Updated dependencies [c4270e476]:

    • @astrojs/markdown-remark@3.3.0

3.2.4

Patch Changes

3.2.3

Patch Changes

3.2.2

Patch Changes

3.2.1

Patch Changes

  • #8680 31c59ad8b Thanks @bluwy! - Fix hydration on slow connection

  • #8698 47ea310f0 Thanks @Princesseuh! - Use a Node-specific image endpoint to resolve images in dev and Node SSR. This should fix many issues related to getting 404 from the _image endpoint under certain configurations

  • #8706 345808170 Thanks @bluwy! - Fix duplicated Astro and Vite injected styles

3.2.0

Minor Changes

  • #8696 2167ffd72 Thanks @matthewp! - Support adding integrations dynamically

    Astro integrations can now themselves dynamically add and configure additional integrations during set-up. This makes it possible for integration authors to bundle integrations more intelligently for their users.

    In the following example, a custom integration checks whether @astrojs/sitemap is already configured. If not, the integration adds Astros sitemap integration, passing any desired configuration options:

    import sitemap from '@astrojs/sitemap';
    import type { AstroIntegration } from 'astro';
    
    const MyIntegration = (): AstroIntegration => {
      return {
        name: 'my-integration',
    
        'astro:config:setup': ({ config, updateConfig }) => {
          // Look for sitemap in user-configured integrations.
          const userSitemap = config.integrations.find(
            ({ name }) => name === '@astrojs/sitemap'
          );
    
          if (!userSitemap) {
            // If sitemap wasnt found, add it.
            updateConfig({
              integrations: [sitemap({ /* opts */ }],
            });
          }
        },
      };
    };
    
  • #8696 2167ffd72 Thanks @matthewp! - View transitions can now be triggered from JavaScript!

    Import the client-side router from "astro:transitions/client" and enjoy your new remote control for navigation:

    import { navigate } from 'astro:transitions/client';
    
    // Navigate to the selected option automatically.
    document.querySelector('select').onchange = (ev) => {
      let href = ev.target.value;
      navigate(href);
    };
    
  • #8696 2167ffd72 Thanks @matthewp! - Route Announcer in <ViewTransitions />

    The View Transitions router now does route announcement. When transitioning between pages with a traditional MPA approach, assistive technologies will announce the page title when the page finishes loading. This does not automatically happen during client-side routing, so visitors relying on these technologies to announce routes are not aware when a page has changed.

    The view transitions route announcer runs after the astro:page-load event, looking for the page <title> to announce. If one cannot be found, the announcer falls back to the first <h1> it finds, or otherwise announces the pathname. We recommend you always include a <title> in each page for accessibility.

    See the View Transitions docs for more on how accessibility is handled.

Patch Changes

3.1.4

Patch Changes

3.1.3

Patch Changes

3.1.2

Patch Changes

3.1.1

Patch Changes

3.1.0

Minor Changes

  • #8467 ecc65abbf Thanks @Princesseuh! - Add a new image.endpoint setting to allow using a custom endpoint in dev and SSR

  • #8518 2c4fc878b Thanks @Princesseuh! - Adds support for using AVIF (.avif) files with the Image component. Importing an AVIF file will now correctly return the same object shape as other image file types. See the Image docs for more information on the different properties available on the returned object.

  • #8464 c92e0acd7 Thanks @Princesseuh! - Add types for the object syntax for style (ex: style={{color: 'red'}})

Patch Changes

3.0.13

Patch Changes

3.0.12

Patch Changes

3.0.11

Patch Changes

3.0.10

Patch Changes

3.0.9

Patch Changes

3.0.8

Patch Changes

3.0.7

Patch Changes

3.0.6

Patch Changes

3.0.5

Patch Changes

3.0.4

Patch Changes

  • #8324 0752cf368 Thanks @matthewp! - Prevent React hook call warnings when used with MDX

    When React and MDX are used in the same project, if the MDX integration is added before React, previously you'd get a warning about hook calls.

    This makes it so that the MDX integration's JSX renderer is last in order.

3.0.3

Patch Changes

3.0.2

Patch Changes

3.0.1

Patch Changes

  • #8290 ef37f9e29 Thanks @matthewp! - Remove "experimental" text from the image config options, for docs and editor etc. text displayed.

  • #8290 ef37f9e29 Thanks @matthewp! - Prevent astro check cache issues

    astro check hits cache issues in 3.0 causing it never to work on the first try.

  • #8283 c32f52a62 Thanks @ematipico! - Add useful warning when deprecated options are still used.

3.0.0

Major Changes

  • #8188 d0679a666 Thanks @ematipico! - Remove support for Node 16. The lowest supported version by Astro and all integrations is now v18.14.1. As a reminder, Node 16 will be deprecated on the 11th September 2023.

  • #8188 364d861bd Thanks @ematipico! - Removed automatic flattening of getStaticPaths result. .flatMap and .flat should now be used to ensure that you're returning a flat array.

  • #8113 2484dc408 Thanks @Princesseuh! - 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.

    ---
    // src/pages/posts/post-1.astro
    - import rocket from '~/assets/rocket.png'
    + import rocket from '../../assets/rocket.png';
    ---
    
  • #8142 81545197a Thanks @natemoo-re! - Fixes for the class:list directive

    • Previously, class:list would ocassionally not be merged the class prop when passed to Astro components. Now, class:list is always converted to a class prop (as a string value).
    • Previously, class:list diverged from clsx in a few edge cases. Now, class:list uses clsx directly.
      • class:list used to deduplicate matching values, but it no longer does
      • class:list used to sort individual values, but it no longer does
      • class:list used to support Set and other iterables, but it no longer does
  • #8179 6011d52d3 Thanks @matthewp! - Astro 3.0 Release Candidate

  • #8188 80f1494cd Thanks @ematipico! - The build.split and build.excludeMiddleware configuration options are deprecated and have been replaced by options in the adapter config.

    If your config includes the build.excludeMiddleware option, replace it with edgeMiddleware in your adapter options:

    import { defineConfig } from "astro/config";
    import netlify from "@astrojs/netlify/functions";
    
    export default defineConfig({
         build: {
    -        excludeMiddleware: true
         },
         adapter: netlify({
    +        edgeMiddleware: true
         }),
    });
    

    If your config includes the build.split option, replace it with functionPerRoute in your adapter options:

    import { defineConfig } from "astro/config";
    import netlify from "@astrojs/netlify/functions";
    
    export default defineConfig({
         build: {
    -        split: true
         },
         adapter: netlify({
    +        functionPerRoute: true
         }),
    });
    
  • #8207 e45f30293 Thanks @natemoo-re! - Change the View Transition built-in animation options.

    The transition:animate value morph has been renamed to initial. Also, this is no longer the default animation.

    If no transition:animate directive is specified, your animations will now default to fade.

    Astro also supports a new transition:animate value, none. This value can be used on a page's <html> element to disable animated full-page transitions on an entire page.

  • #8188 c0de7a7b0 Thanks @ematipico! - Sharp is now the default image service used for astro:assets. If you would prefer to still use Squoosh, you can update your config with the following:

    import { defineConfig, squooshImageService } from 'astro/config';
    
    // https://astro.build/config
    export default defineConfig({
      image: {
        service: squooshImageService(),
      },
    });
    

    However, not only do we recommend using Sharp as it is faster and more reliable, it is also highly likely that the Squoosh service will be removed in a future release.

  • #8188 3c3100851 Thanks @ematipico! - Remove support for Astro.__renderMarkdown which is used by @astrojs/markdown-component.

    The <Markdown /> component was deprecated in Astro v1 and is completely removed in v3. This integration must now be removed from your project.

    As an alternative, you can use community packages that provide a similar component like https://github.com/natemoo-re/astro-remote instead.

  • #8019 34cb20021 Thanks @bluwy! - Remove backwards-compatible kebab-case transform for camelCase CSS variable names passed to the style attribute. If you were relying on the kebab-case transform in your styles, make sure to use the camelCase version to prevent missing styles. For example:

    ---
    const myValue = 'red';
    ---
    
    <!-- input -->
    <div style={{ '--myValue': myValue }}></div>
    
    <!-- output (before) -->
    <div style="--my-value:var(--myValue);--myValue:red"></div>
    
    <!-- output (after) -->
    <div style="--myValue:red"></div>
    
    <style>
      div {
    -   color: var(--my-value);
    +   color: var(--myValue);
      }
    </style>
    
  • #8170 be6bbd2c8 Thanks @bluwy! - Remove deprecated config option types, deprecated script/style attributes, and deprecated image export from astro:content

  • #8188 7511a4980 Thanks @ematipico! - When using an adapter that supports neither Squoosh or Sharp, Astro will now automatically use an image service that does not support processing, but still provides the other benefits of astro:assets such as enforcing alt, no CLS etc to users

  • #7979 dbc97b121 Thanks @bluwy! - Export experimental dev, build, preview, and sync APIs from astro. These APIs allow you to run Astro's commands programmatically, and replaces the previous entry point that runs the Astro CLI.

    While these APIs are experimental, the inline config parameter is relatively stable without foreseeable changes. However, the returned results of these APIs are more likely to change in the future.

    import { dev, build, preview, sync, type AstroInlineConfig } from 'astro';
    
    // Inline Astro config object.
    // Provide a path to a configuration file to load or set options directly inline.
    const inlineConfig: AstroInlineConfig = {
      // Inline-specific options...
      configFile: './astro.config.mjs',
      logLevel: 'info',
      // Standard Astro config options...
      site: 'https://example.com',
    };
    
    // Start the Astro dev server
    const devServer = await dev(inlineConfig);
    await devServer.stop();
    
    // Build your Astro project
    await build(inlineConfig);
    
    // Preview your built project
    const previewServer = await preview(inlineConfig);
    await previewServer.stop();
    
    // Generate types for your Astro project
    await sync(inlineConfig);
    
  • #8188 7d2f311d4 Thanks @ematipico! - Removed support for old syntax of the API routes.

  • #8085 68efd4a8b Thanks @bluwy! - Remove exports for astro/internal/* and astro/runtime/server/* in favour of astro/runtime/*. Add new astro/compiler-runtime export for compiler-specific runtime code.

    These are exports for Astro's internal API and should not affect your project, but if you do use these entrypoints, you can migrate like below:

    - import 'astro/internal/index.js';
    + import 'astro/runtime/server/index.js';
    
    - import 'astro/server/index.js';
    + import 'astro/runtime/server/index.js';
    
    import { transform } from '@astrojs/compiler';
    
    const result = await transform(source, {
    - internalURL: 'astro/runtime/server/index.js',
    + internalURL: 'astro/compiler-runtime',
      // ...
    });
    
  • #7893 7bd1b86f8 Thanks @ematipico! - Implements a new scope style strategy called "attribute". When enabled, styles are applied using data-* attributes.

    The default value of scopedStyleStrategy is "attribute".

    If you want to use the previous behaviour, you have to use the "where" option:

    import { defineConfig } from 'astro/config';
    
    export default defineConfig({
    +    scopedStyleStrategy: 'where',
    });
    
  • #7924 519a1c4e8 Thanks @matthewp! - Astro's JSX handling has been refactored with better support for each framework.

    Previously, Astro automatically scanned your components to determine which framework-specific transformations should be used. In practice, supporting advanced features like Fast Refresh with this approach proved difficult.

    Now, Astro determines which framework to use with include and exclude config options where you can specify files and folders on a per-framework basis. When using multiple JSX frameworks in the same project, users should manually control which files belong to each framework using the include and exclude options.

    export default defineConfig({
      // The `include` config is only needed in projects that use multiple JSX frameworks;
      // if only using one no extra config is needed.
      integrations: [
        preact({
          include: ['**/preact/*'],
        }),
        react({
          include: ['**/react/*'],
        }),
        solid({
          include: ['**/solid/*'],
        }),
      ],
    });
    
  • #8030 5208a3c8f Thanks @natemoo-re! - Removed duplicate astro/dist/jsx export. Please use the astro/jsx export instead

  • #8188 84af8ed9d Thanks @ematipico! - Remove MDX plugin re-ordering hack

  • #8180 f003e7364 Thanks @ematipico! - The scoped hash created by the Astro compiler is now lowercase.

  • #7878 0f637c71e Thanks @bluwy! - The value of import.meta.env.BASE_URL, which is derived from the base option, will no longer have a trailing slash added by default or when trailingSlash: "ignore" is set. The existing behavior of base in combination with trailingSlash: "always" or trailingSlash: "never" is unchanged.

    If your base already has a trailing slash, no change is needed.

    If your base does not have a trailing slash, add one to preserve the previous behaviour:

    // astro.config.mjs
    - base: 'my-base',
    + base: 'my-base/',
    
  • #8118 8a5b0c1f3 Thanks @lilnasy! - Astro is smarter about CSS! Small stylesheets are now inlined by default, and no longer incur the cost of additional requests to your server. Your visitors will have to wait less before they see your pages, especially those in remote locations or in a subway.

    This may not be news to you if you had opted-in via the build.inlineStylesheets configuration. Stabilized in Astro 2.6 and set to "auto" by default for Starlight, this configuration allows you to reduce the number of requests for stylesheets by inlining them into