Astro 5.7

By
Matt Kane
Florian Lefebvre
Emanuele Stoppa
Nate Moore

Astro 5.7 has a basketload of treats, including stable Sessions and SVG components and a new Experimental Fonts API.

🐣 Full of the joys of northern-hemisphere spring, Astro 5.7 is here with goodies galore:

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

Experimental Fonts API

Almost every website these days uses custom fonts. However, it can be surprisingly complicated to get them right: Why do I get a Flash of Unstyled Text? Should I add a preload link? What about preconnect links? Do I self-host or rely on a third-party provider?

Fonts can have significant performance implications on your site, affecting your visitors’ browsing experience and important Core Web Vitals (CWV) metrics. Fortunately, web APIs have greatly improved recently and thanks to amazing initiatives of the open source community (eg. unifont and capsize), we’ve been able to start working on a great way to use fonts in Astro!

This experimental feature allows you to use fonts from both your file system and several built-in supported providers (e.g. Google, Fontsource, Bunny) through a unified API. Keep your site performant thanks to sensible defaults and automatic optimizations including fallback font generation.

To enable this feature, configure an experimental.fonts object with one or more fonts:

astro.config.mjs
import { defineConfig, fontProviders } from "astro/config";
export default defineConfig({
experimental: {
fonts: [{
provider: fontProviders.google(),
name: "Roboto",
cssVariable: "--font-roboto"
}]
}
});

Then, add a <Font /> component and site-wide styling in your <head>:

src/components/Head.astro
---
import { Font } from 'astro:assets'
---
<Font cssVariable='--font-roboto' preload />
<style>
body {
font-family: var(--font-roboto);
}
</style>

There’s so much more to discover! Head over to the experimental Fonts documentation for the full API, how to get started, and even how to build your own custom AstroFontProvider if we don’t yet support your preferred font service.

We’d also appreciate your feedback. Participate in the ongoing development of this feature on the Fonts RFC and help shape its future.

Sessions API

The Astro Sessions API is now stable and ready for production!

Sessions let you securely store data tied to a specific user as they navigate between pages on your site. Unlike cookies, sessions are stored on the server, so you can store larger amounts of data without worrying about size limits or security issues. They are useful for storing things like user data, shopping carts, and form state, and they work without any client-side JavaScript:

src/components/CartButton.astro
---
const cart = await Astro.session.get('cart');
export const prerender = false;
---
<a href="/checkout">šŸ›’ {cart?.length ?? 0} items</a>

They can be used in Astro components, pages, API endpoints, actions, and middleware. The API is the same for all of them:

src/actions/addToCart.ts
import { defineAction } from "astro:actions";
import { z } from "astro:schema";
export const server = {
addToCart: defineAction({
input: z.object({
product: z.string(),
}),
async handler({ product }, { session }) {
const cart = await session.get('cart');
session.set('cart', [...cart, product]);
},
}),
};

Type-safety

Of course, as this is Astro, your sessions can be type-safe too. Define an interface and you will get type-checking and auto-completion for all of your session data:

src/env.d.ts
declare namespace App {
interface SessionData {
user: {
id: string;
name: string;
};
cart: string[];
}
}

The session ID is automatically tracked using a cookie, but you can also use the session.load() method to access sessions without cookies. This is useful for things like APIs, where you might want to use a custom header or params to track the session ID:

src/pages/api/cart.ts
export async function POST({ session, request }: APIContext) {
const sessionId = request.headers.get('x-session-id');
// If there is an existing session ID, load it. Otherwise, one will be created
if (sessionId) {
await session.load(sessionId);
}
const cart = await session.get('cart');
const data = await request.json<{ item: string }>();
if (!data?.item) {
return new Response('Item is required', { status: 400 });
}
session.set('cart', [...cart, data.item]);
// Return the cart and session ID
return Response.json({ cart, sessionId: session.sessionId });
}

Storage drivers

Astro sessions use storage drivers to persist the data, and these are either zero-config or require minimal setup for all official Astro adapters. Alternatively, you can use any unstorage driver, which supports dozens of storage backends such as Redis and MongoDB.

  • Node: zero-config filesystem driver
  • Netlify: zero-config Netlify Blobs driver
  • Cloudflare: minimal-config Workers KV driver
  • Vercel: minimal-config Redis/Upstash driver

On any of these platforms, you can easily switch out the driver for a different one if you don’t want to use the default.

astro.config.mjs
import { defineConfig } from 'astro/config';
import netlify from '@astrojs/netlify';
export default defineConfig({
// ...
adapter: netlify(),
session: {
driver: 'redis',
options: {
url: process.env.REDIS_URL,
},
},
});

Upgrading from experimental sessions

If you were using the experimental sessions API, you should remove the experimental flag from your astro.config.mjs file:

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// ...
experimental: {
session: false,
},
});

Check out the sessions guide to learn more about how to use them in your Astro project.

SVG Components

Astro now supports local SVG files as components! Inlining SVGs directly into your HTML had previously required extra steps like manually converting the SVG to an Astro component or installing a third-party integration. Now, Astro supports using the default import of any .svg file as you would use any other .astro component. SVG components automatically inline an <svg> tag directly into your HTML.

You can pass props such as width, height, fill, stroke, and any other attribute accepted by the native <svg> element.

src/components/MyAstroComponent.astro
---
import Logo from './path/to/svg/file.svg';
---
<Logo width={64} height={64} fill="currentColor" />

Take a look at the SVG components documentation for more details.

Special thanks to Michael Stramel for his work on this feature!

Upgrading from experimental SVG

If you were previously using the experimental SVG API, you must remove the experimental flag from your astro.config.mjs file.

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

Note that Astro 5.6 introduced some breaking changes to this flag. Please check that your code is up-to-date with the latest, stable version of this API.

Config Imports

The new virtual module astro:config is now stable!

The virtual module allows you to import a subset of the Astro configuration, with type-safety in mind. Two sub-paths are exposed for controlled access to your configuration:

  • astro:config/client: exposes config information that is safe to expose to the client.
  • astro:config/server: exposes additional information that is safe to expose to the server, such as file/dir paths.

For example, you can now build your own path utilities without relying on an integration. Properties like base and trailingSlash set in your configuration can be imported and used in a .js file:

astro.config.mjs
export default defineConfig({
base: "store/",
trailingSlash: "always"
});
src/utils.js
import { trailingSlash, base } from 'astro:config/client';
// This method adds a forward slash to paths, and prepends the `base`
function addForwardSlashAndBase(path) {
let finalPath;
if (trailingSlash === 'always') {
finalPath = path.endsWith('/') ? path : path + '/';
} else {
finalPath = path;
}
if (base !== "/") {
return base + finalPath
}
return finalPath
}

Use this path utility that depends on your configuration settings throughout your project, for example, for more control over page links:

src/pages/index.astro
---
import { addForwardSlashAndBase } from "@src/utils.js";
const cartUrl = addForwardSlashAndBase("cart"); // it will return "store/cart/"
---
<a href={cartUrl}>Cart</a>

We configured you’d enjoy this new ability to access your settings, with Astro’s trademark type safety to help you get it right!

Bug fixes

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

Community

The Astro core team is:

Ben Holmes , Caleb Jasik , Chris Swithinbank , Emanuele Stoppa , Erika , Florian Lefebvre , Fuzzy , HiDeoo , Luiz Ferraz , Matt Kane , Matthew Phillips , Nate Moore , Reuben Tier , Sarah Rainsberger , and Yan Thomas .

Thanks to all the other contributors who helped make Astro 5.7 possible, including: Roberto Molina, Junseong Park, ryu, Martin Trapp, Michael Stramel, Armand Philippot, Nin3, viniciusdeliz, Juan Diaz, Marcos Corrochano Arroyo, Paul Valladares, Bugo, liruifengv, Thomas Bonnet, Ming-jun Lu, CHEZ, omoyx, emily-shen, Ariel K, Maciek Palmowski, Matthew Justice, Adam Matthiesen, and Louis Escher.

We look forward to seeing what you build with Astro 5.7! If you have questions, comments, or just want to say hi, drop by the Astro Discord.

Astro 5.6

Astro 5.6 brings first-class astro:env and experimental session support to Cloudflare, and gives more control over prefetching.

Astro 5.5

Astro 5.5 dives deep with better support for diagramming tools, improved Markdown compatibility, and type-safe sessions!