Gatsby to Astro: Why I Finally Migrated
My site started in 2017 and had been stuck on Gatsby 2.28.2 for years. React 16, Ant Design v3, D3 v5 - everything was outdated. Security warnings kept piling up. Build times were slow. I’d been putting off the migration for too long.
Last week, I finally did it. Moved 22 articles and 14 data visualizations from Gatsby to Astro 4.x. Here’s what I learned.
Why Astro over Next.js?
I looked at Next.js, Remix, and Astro. For a content-heavy site like mine, Astro made the most sense:
- Zero JS by default - ships only what you need
- Partial hydration - interactive components load JS, static ones don’t
- Framework agnostic - I could keep my React components
- Vite-powered - fast HMR, modern tooling
The philosophy clicked: ship HTML, sprinkle JavaScript when necessary.
The Migration
Content was easy
Astro’s content collections handle markdown beautifully. I wrote a quick script to convert frontmatter:
// Convert Gatsby format to Astro
// written: "2018-10-02" → date: 2018-10-02
// category: "Deep Learning" → tags: ["Deep Learning"]
6 markdown articles migrated in minutes.
React components were trickier
16 of my articles were React components with interactivity, API calls, and visualizations. The solution: convert to MDX and use client directives.
import VegaChart from '@/components/VegaChart.tsx';
# My Article
<VegaChart client:visible specUrl="..." />
The client:visible directive is nice - only loads JS when the component scrolls into view.
Ant Design had to go
Ant Design v3 was the biggest dependency. I replaced it with Tailwind CSS. More work upfront, but the bundle size dropped dramatically.
Visualizations needed rewiring
My Plotly and Vega charts didn’t play well with Astro’s hydration. I ended up converting most to ECharts using echarts-for-react. Some gotchas:
- Raw
echarts.init()doesn’t work reliably with React hydration react-scrollamafails with Astro - use native IntersectionObserver insteadvis-networkhas CommonJS issues with Vite
I documented these in a GOTCHAS.md file for future reference.
Results
The numbers speak for themselves:
| Metric | Gatsby | Astro |
|---|---|---|
| First Contentful Paint | ~2.5s | ~0.5s |
| JS Bundle | ~300KB | ~30KB |
| Lighthouse Performance | 60 | 95 |
5x faster page loads. 10x smaller JavaScript.
What I’d Do Differently
Use git worktrees from the start. I worked in a separate directory which made comparing old and new versions easy.
Don’t rewrite everything. If a React component works, keep it as React. Astro supports mixing frameworks.
Automate the boring stuff. Claude Code helped with bulk frontmatter conversion and finding broken image paths. The repetitive parts went fast.
Worth It?
Yes. The site feels snappier, the codebase is cleaner, and I’m no longer dreading dependency updates. Should have done this sooner.
If you’re stuck on an old Gatsby version, Astro is a solid choice for content sites. The migration isn’t trivial, but the payoff is real.