Astro 7: What Changed and What to Use
A tour of the Astro 7 features that actually affect day-to-day work — Content Layer API, font management, ClientRouter, and the Rolldown migration.
Astro 7 lands with a new bundler (Rolldown), a stable Content Layer API, and several deprecations that have caught me out. Here’s what actually changes in practice.
Content Layer API: content.config.ts + Loaders
The old src/content/config.ts file is gone in favour of
src/content.config.ts (note the leading dot). Collections now use a
loader from astro/loaders:
import { defineCollection } from "astro:content";
import { glob } from "astro/loaders";
import { z } from "astro/zod";
const blog = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/content/blog" }),
schema: z.object({ /* ... */ }),
});
Three things to internalise:
- Import Zod from
astro/zod, not standalonezod. Astro re-exports a version that’s compatible with its content layer. post.idincludes the directory prefix when using the glob loader. A post atsrc/content/blog/en/hello.mdxhas iden/hello, nothello. Strip the locale prefix before using it as a URL slug.Astro.glob()is gone. UsegetCollection()orimport.meta.glob.
The Fonts API
Manual @font-face declarations are out. Configure fonts in
astro.config.mjs:
import { defineConfig, fontProviders } from "astro/config";
export default defineConfig({
fonts: [
{
provider: fontProviders.local(),
name: "Satoshi",
cssVariable: "--font-display",
options: { variants: [/* ... */] },
},
],
});
Astro handles the @font-face generation, the variable wiring, and the
preload hints. You reference the font via the CSS variable in your Tailwind
theme tokens.
View Transitions: <ClientRouter />
<ViewTransitions /> is removed. Import <ClientRouter /> from
astro:transitions instead:
---
import { ClientRouter } from "astro:transitions";
---
<head>
<ClientRouter />
</head>
The lifecycle events renamed accordingly: astro:page-load replaces
astro:after-swap for “navigation completed” hooks (both fire, but
astro:page-load is the one you want for re-initialising client-side
state).
Tailwind 4: The Vite Plugin
@astrojs/tailwind is deprecated. Use the Vite plugin directly:
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
vite: { plugins: [tailwindcss()] },
});
Dark mode variants move into global.css:
@custom-variant dark (&:where(.dark, .dark *));
The Rolldown Migration
Astro 7 ships Rolldown (a Rust-backed Rollup replacement) as the default bundler. In practice this means faster builds and smaller outputs, but a few integrations haven’t caught up:
- Some Vite plugins that depend on Rollup internals break.
- PWA integrations that hook into the build graph may need updates.
When an integration breaks, the symptom is usually a build-time error about a missing export or a worker resolution failure. File an issue and pin the Astro version in the meantime.
Container API
The Container API (introduced experimentally in 5.x) is stable. Import renderers from the container-renderer subpath:
import { experimental_AstroContainer as AstroContainer } from "astro/container";
import { getContainerRenderer as getMDXRenderer } from "@astrojs/mdx/container-renderer";
This is what powers component unit tests.
Verdict
Astro 7’s headline is performance, but the day-to-day wins are the Content
Layer API and the deprecation cleanup. The migration is mostly mechanical —
search-and-replace Astro.glob, swap ViewTransitions, fix the Tailwind
plugin — and the result is a faster, more consistent codebase.