---
title: "Astro 7 dropped the day after I finished my Astro 6 migration"
url: "https://alex.zappa.dev/blog/astro7-update/"
description: "The universe has a sense of humor. I published my migration story, went to sleep, and woke up to Astro 7. Here's what broke, what I fixed, and why I'm not even mad."
---

# Astro 7 dropped the day after I finished my Astro 6 migration

June 23, 2026

*   [#astro](/tags/astro/),
*   [#migration](/tags/migration/),
*   [#tailwind](/tags/tailwind/),
*   [#css](/tags/css/)

Yesterday I published a [3,000-word post](/blog/astro6-migration/) about migrating my entire stack from Eleventy to Astro 6. Benchmarks, philosophy, the whole thing. I hit publish, felt good about it, and went to sleep.

I woke up to Astro 7.

Not a release candidate. Not a beta. The actual `astro@7.0.0`, sitting on npm, looking at me like it knew exactly what it was doing.

![Speedometer comparison showing Astro 6 at 70% and Astro 7 at 95% build performance](/_astro/astro7-migration.Ba1IrLi8_gxuOx.webp)

## The upgrade command is a trap

Astro ships an `npx astro upgrade` command that handles the migration for you. It updates dependencies, rewrites config, and prints a cheerful summary of what changed. I ran it. It worked. The output looked clean. I thought I was done.

I was not done.

The upgrade command is good at the mechanical stuff: bumping version numbers, swapping deprecated APIs for their replacements, updating the markdown config to use the new `unified()` processor. What it can’t do is tell you that your dependency tree is about to implode, or that your CSS is going to silently lose half its rules. That part is on you.

## Sharp: the native binary that couldn’t

The first thing that broke was `sharp`. Not because of Astro 7 directly, but because I’d bumped it to `0.35.2` (the latest) while `astro-compress` and `miniflare` (inside `wrangler`) both pinned `0.34.5`. npm dutifully installed three copies of sharp at different versions, and the `0.34.5` one tried to build from source because it has no prebuilt binaries for macOS 26 (Darwin 25.5.0).

The build-from-source path needs `node-addon-api` and `node-gyp`, which I didn’t have, so it failed. The error message was the kind of thing that makes you question your career choices:

```
sharp: Attempting to build from source via node-gyp
sharp: Please add node-addon-api to your dependencies
```

The fix was npm `overrides`, forcing every transitive sharp dependency to resolve to the project’s direct `0.35.2`:

```
"overrides": {
  "astro-compress": { "sharp": "$sharp" },
  "miniflare": { "sharp": "$sharp" }
}
```

The `$sharp` syntax tells npm “use whatever version the project itself declares.” One copy of sharp, one set of prebuilt binaries, zero build-from-source nightmares. This is the kind of thing that works perfectly on your machine and then explodes in CI because the Linux runner has a different glibc. Overrides are your insurance policy.

## The media queries that vanished

This one was weirder. The site built fine locally. Tailwind was working. Dark mode toggled. Everything looked correct in dev. But the production build, the one that runs through `astro-compress`, was missing responsive behavior. Tables didn’t stack on mobile. The CodePen embed wrapper didn’t adjust at small screens.

I diffed the CSS output and found the smoking gun. My hand-written media queries:

```
@media (max-width: 640px) { … }
@media (min-width: 640px) { … }
```

Had become, in the production CSS file, absolutely nothing. Gone. Deleted. Not minified. Erased.

The chain of events is a beautiful little tragedy in three acts:

1.  **Astro 7 switched its compiler from Go to Rust.** The new Rust compiler uses Lightning CSS under the hood for CSS processing.
2.  **Lightning CSS transforms standard media queries into range syntax.** `max-width: 640px` becomes `width<=640px`. This is valid CSS Media Queries Level 4. It’s the modern way to write them. Lightning CSS is doing the right thing.
3.  **csso, the CSS minifier inside astro-compress, doesn’t understand range syntax.** It sees `@media (width<=640px)` and thinks “I don’t know what this is, probably redundant, delete it.”

So the pipeline was: write valid CSS → Lightning CSS modernizes it → csso eats it. The Go compiler never did that transformation, so csso never choked on it. The Rust compiler does, and suddenly your responsive layout is gone.

The fix was one line in `astro.config.mjs`:

```
(await import('astro-compress')).default({ CSS: false }),
```

astro-compress still minifies HTML, JavaScript, SVG, and images. It just leaves CSS alone. The Tailwind output is already well-optimized, and the ~40 KB CSS file isn’t worth fighting a minifier over.

## Tailwind v4 adjustments

Astro 7 ships with first-class Tailwind v4 support via the `@tailwindcss/vite` plugin. The migration was mostly smooth. The `@theme` block, `@layer` directives, and `@custom-variant` for dark mode all carried over cleanly. The main thing I had to adjust was the `@import` and `@source` directives at the top of `global.css`:

```
@import "tailwindcss" source("../");
@source "../**/*.astro";
```

Tailwind v4 uses CSS-based configuration instead of a separate `tailwind.config.js`, which is honestly a win. One less file to maintain.

## Was this Astro’s fault?

No. Let me be clear about where the bugs actually live:

*   **The sharp conflict** is a dependency management problem. astro-compress and miniflare pin older sharp versions that don’t have binaries for new macOS releases. npm overrides are the standard fix.
*   **The media query bug** is in csso, not Astro. csso hasn’t had a release in over a year and doesn’t support CSS range syntax. Lightning CSS (which astro-compress already bundles as a dependency) handles it fine; the fix would be for astro-compress to switch its CSS minifier from csso to lightningcss.
*   **The Go→Rust compiler change** is a feature, not a bug. It’s faster, it enables new optimizations, and the range-syntax transformation is correct modern CSS. The only problem is that a downstream tool hasn’t caught up.

## The bright side

Here’s the thing: after fixing those two issues, everything else just worked. The build is fast. The output is clean. The site scores 100s on PageSpeed Insights. Astro 7’s new compiler is genuinely quicker, and the Rust-based pipeline feels snappier even on warm rebuilds.

I spent maybe two hours debugging total. For a major version bump that landed the day after I finished a full stack migration, that’s honestly not bad. The upgrade command handled 90% of the mechanical work. The remaining 10% was dependency tree surgery and a one-line config change.

I’m not even mad. The timing is objectively hilarious. But the platform is solid, the fixes were straightforward, and I’d rather debug two issues in an evening than spend a weekend hand-wiring a build pipeline. Astro 7 is a good release. Just… maybe wait a day after your migration post before you run the upgrade.

May the 4th be with you,  
Alex

*   [PreviousWhy I migrated my stack from Eleventy to Astro 6](/blog/astro6-migration/)