Astro 5.15

By
Matthew Phillips

🎃 Astro 5.15 brings automatic Netlify skew protection, granular font preload filtering, and powerful new APIs for adapters.

Explore what’s new in this release:

To upgrade an existing project, use the automated @astrojs/upgrade CLI tool. Alternatively, upgrade manually by running the upgrade command for your package manager:

# Recommended:
npx @astrojs/upgrade
# Manual:
npm install astro@latest
pnpm upgrade astro --latest
yarn upgrade astro --latest

Netlify skew protection

Astro 5.15 introduces automatic skew protection for Netlify deployments, ensuring your site’s client and server versions stay perfectly synchronized.

Deployment skew is a sneaky issue that occurs when users load older client assets while the server is running newer code. This can cause subtle bugs and unexpected behavior that are hard to track down. With Netlify skew protection, this is now a thing of the past.

When you deploy to Netlify, Astro automatically includes your deployment ID in all asset requests and API calls. This allows Netlify to detect and handle any version mismatches automatically—no configuration needed. Your site just works, even during rapid deployments or when users are on slow connections that might load assets across deployment boundaries.

If you’re making custom fetch requests in your application, you can also access the deployment ID directly:

const deployId = import.meta.env.DEPLOY_ID;
const response = await fetch('/api/endpoint', {
headers: {
'x-deploy-id': deployId,
},
});

Netlify skew protection works seamlessly across all of Astro’s core features, including View Transitions, Server Islands, Prefetch, and Astro Actions, giving you peace of mind across your entire site.

New adapter APIs for customizing headers and assets

Behind the scenes, Netlify’s skew protection is powered by a new set of core APIs that allow adapters to customize both headers and asset query parameters across Astro’s systems.

Astro now exposes a client configuration option in the AstroAdapter interface, allowing adapters to specify:

  • internalFetchHeaders - Custom headers that should be automatically included in all fetch calls made by Astro’s core systems (Actions, View Transitions, Server Islands, and Prefetch)
  • assetQueryParams - Query parameters that should be automatically appended to asset URLs

This gives hosting platforms the hooks they need to implement sophisticated features like skew protection without requiring manual configuration from developers.

Here’s how an adapter configures these options in the astro:config:done hook:

exampleAdapter/index.ts
export default function exampleAdapter() {
return {
name: 'example-adapter',
hooks: {
'astro:config:done': async ({ setAdapter }) => {
setAdapter({
name: 'example-adapter',
serverEntrypoint: 'example-adapter/ssr.js',
client: {
internalFetchHeaders: () => {
const deployId = process.env.DEPLOY_ID;
if (deployId) {
return { 'x-deploy-id': deployId };
}
return {};
},
assetQueryParams: process.env.DEPLOY_ID
? new URLSearchParams({ deployId: process.env.DEPLOY_ID })
: undefined,
},
});
},
},
};
}

The Vercel adapter now also benefits from these new APIs. Previously, Vercel’s skew protection had some limitations and bugs that prevented it from working correctly across all of Astro’s features. With this update, the Vercel adapter now uses the same new APIs to provide reliable skew protection when the VERCEL_SKEW_PROTECTION_ENABLED environment variable is enabled, bringing it to feature parity with Netlify.

Granular font preload filtering

The experimental Fonts API now supports granular control over which font variants get preloaded. Previously, you could only choose to preload all variants of a font or none at all. Now you can specify exactly which weights, styles, and subsets should be preloaded, helping you optimize performance by downloading only what you actually use.

When using the <Font> component, you can pass a preload array to filter variants:

---
import { Font } from 'astro:assets';
---
<Font
cssVariable="--font-roboto"
preload={[
{ subset: 'latin', style: 'normal' },
{ weight: '400' },
]}
/>

This example will only preload the Latin subset in normal style and any font files with a weight of 400. For variable weight fonts (which support a range like 100–900), Astro intelligently matches them against your filter criteria. Requesting weight 400 will include a variable font that covers the 100–900 range, since it supports that weight.

You can filter on any combination of:

  • weight - Specific font weight (e.g., '400', '700')
  • style - Font style (e.g., 'normal', 'italic')
  • subset - Font subset (e.g., 'latin', 'cyrillic')

This gives you fine-grained control over your font loading strategy, reducing unnecessary downloads while maintaining design flexibility.

Other improvements

  • Copy button for stack traces – The error overlay now includes a copy button to easily share stack traces with LLMs and AI editors for faster debugging. Thanks to Deveesh Shetty for contributing this feature! (#14489)
  • Wrangler configuration scaffolding – The astro add CLI now automatically scaffolds wrangler.jsonc when adding Cloudflare integration. Thanks to Oliver Speir for updating our Cloudflare documentation with updated guidance! (#14564)
  • Node.js 18 deprecation – The Vercel adapter now marks Node.js 18 as deprecated in favor of newer LTS versions. Thanks to Jacob Lamb for this contribution! (#14555)

Bug fixes

As always, we’ve been working hard on fixing issues since the 5.14 release. See the changelog for all the details.

Community

The Astro core team is:

Alexander Niebuhr , Armand Philippot , Chris Swithinbank , Emanuele Stoppa , Erika , Florian Lefebvre , Fred Schott , HiDeoo , Luiz Ferraz , Matt Kane , Matthew Phillips , Reuben Tier , Sarah Rainsberger , and Yan Thomas .

Thanks to all the other contributors who helped make Astro 5.15 possible with code and docs additions and improvements, including:

Abdelrahman Abdelfattah, Alasdair McLeay, Alvaro Saburido, aprici7y, Aron Homberg, Bartosz Kapciak, Brian Dukes, Deveesh Shetty, Dinotaurent, Edward Brunetiere, Elian, Ewelina Bierć, Eyoz, Felix Schneider, Hunter Bertoson, Jacob Lamb, James Joseph Finn, Jeffrey Yasskin, Jonas Geiler, Junseong Park, kato takeshi, Kenzo Wada, knj, liruifengv, Louis Escher, Mads Erik Forberg, Martin Trapp, Matthew Justice, Maurici Abad Gutierrez, Nin3, Olcan EBREM, Oliver Speir, Paul Sachs, paul valladares, randomguy-2650, Razon Yang, Ricardo Cuauro, Robin Bühler, Sankalpa Acharya, Sebastian Beltran, Steven, Tarik, Thomas Bonnet, Timon Jurschitsch, vrabe, Xidorn Quan, and Yorukot