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.

·3 min read
astrotypescriptweb

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:

  1. Import Zod from astro/zod, not standalone zod. Astro re-exports a version that’s compatible with its content layer.
  2. post.id includes the directory prefix when using the glob loader. A post at src/content/blog/en/hello.mdx has id en/hello, not hello. Strip the locale prefix before using it as a URL slug.
  3. Astro.glob() is gone. Use getCollection() or import.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.