Back to Blog

Migrating My Personal Site from Astro 2 to Astro 6

· 4 min read

I’ve been running my personal site on Astro since 2023, but it was stuck on version 2.7. With Astro 6 out and a lot of improvements I wanted to make, I decided to tackle the full migration. Here’s what I learned jumping four major versions in one session.

Why Upgrade?

Astro 2.7 was solid, but the ecosystem had moved on. The new Content Layer API, better image optimization, and Vite 7 were too good to ignore. Plus, my site had accumulated some technical debt — CSS bugs, hardcoded values, and a homepage that was just a logo and an avatar.

The Migration Path: v2 → v3 → v4 → v5 → v6

Jumping four major versions sounds scary, but Astro’s migration guides are well documented. Here are the key breaking changes I had to deal with:

Content Collections → Content Layer API

This was the biggest change. The old src/content/config.ts became src/content.config.ts, and every collection now needs a loader:

import { glob } from "astro/loaders";

const blogCollection = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    // ...
  }),
});

slug → id

Every reference to post.slug had to change to post.id. This affected all dynamic routes, listing pages, and the RSS feed.

render() is now imported

Instead of calling post.render(), you now import render from astro:content:

import { render } from "astro:content";
const { Content } = await render(post);

RSS endpoint: get → GET

The RSS endpoint function name changed from lowercase get to uppercase GET to match HTTP method conventions.

astro-icon v0.8 → v1

The import path changed from astro-icon to astro-icon/components, and the package now needs to be registered as an integration in astro.config.mjs. I also had to install @iconify-json/mdi for the Material Design Icons.

Migrating from npm to Bun

While I was at it, I switched from npm to Bun. The process was simple:

  1. Delete node_modules and package-lock.json
  2. Run bun install
  3. Update scripts in package.json to use bunx --bun

Build times went from ~1.6s to ~1.1s. Not a huge difference for a small site, but bun install is noticeably faster than npm install.

What I Fixed Along the Way

The migration was also a chance to fix bugs I’d been ignoring:

  • An extra } in the Header CSS that broke styles
  • width: 100vph (not a real unit) → 100%
  • A typo in the class name porfolioportfolio
  • margin-top: 1rem 0 (invalid shorthand) → margin: 1rem 0
  • Empty alt attributes on images
  • A duplicate color property in a hover state
  • The component BackButtom.astroBackButton.astro

The Redesign

With clean code as a foundation, I redesigned the entire site:

  • New color palette — Navy, Teal, Sky Blue, and Beige
  • Homepage — Hero section with CTA buttons, skills grid, open source preview, and dev setup
  • About page — Full career timeline from 1988 to 2026
  • Open Source page — Showcasing my Go and Rust projects
  • Portfolio — Redesigned cards with tech tags
  • Footer — Consistent across all pages with social links
  • 404 page — Custom error page
  • SEO — robots.txt, og:image, meta author, dynamic descriptions

Tools I Used

I used Claude Code extensively throughout this process. It helped me read the migration guides, identify breaking changes, update all the files, and catch bugs. Having an AI assistant that can read documentation, understand the codebase, and make changes across multiple files simultaneously made this migration much faster than doing it manually.

Lessons Learned

  1. Don’t fear major version jumps — Astro’s migration guides are thorough. Read them carefully and make changes methodically.
  2. Fix bugs while you’re in there — A migration is the perfect time to clean up technical debt.
  3. CSS custom properties save time — Changing the entire color palette was just editing 4 variables.
  4. Bun is a drop-in replacement — The migration from npm took about 2 minutes.
  5. Use AI tools — They’re great for tedious migration work and catching things you’d miss.

Result

The site went from a basic template with a logo and avatar to a full professional portfolio with 6 pages, optimized images, proper SEO, and a consistent design system. And it all deploys automatically on Vercel with every git push.

If you’re still on an old version of Astro, I’d encourage you to make the jump. The new Content Layer API alone is worth it.