613 words
3 minutes
Moving from Gatsby to Astro: Embracing Simplicity

When everything in your development setup works just fine, it’s easy to ignore that nagging sensation that you might be missing out on something better. That’s exactly where I found myself with my Gatsby blog a few months ago.

The Perfect Excuse for Change#

I kept seeing Astro mentioned in tech discussions, often accompanied by excited developers sharing surprisingly small bundle sizes and build times that made me do a double-take. Still, I probably would have stayed in my comfort zone if it weren’t for a seemingly unrelated issue: I needed to reorganize my blog’s content structure.

“If I’m going to reorganize everything anyway,” I thought, “maybe this is the perfect time to try something new…”

First Contact with Astro#

The initial setup was surprisingly quick. After years of watching create-react-app and Gatsby’s build processes, the speed of Astro’s initialization felt almost suspicious:

npm create astro@latest

But the real “aha” moment came when moving my first blog posts. Instead of spending hours configuring a data layer, I found myself simply writing Markdown in a content folder. No complexity, no ceremony—just content where it belonged.

Content Collections: The Feature I Didn’t Know I Needed#

Just as I was getting comfortable with Astro’s straightforward approach, I discovered content collections. At first glance, they seemed like another arbitrary abstraction. Then I saw their true value: they create a strict contract between content and code.

const blogSchema = z.object({
  title: z.string(),
  publishDate: z.date(),
  tags: z.array(z.string()),
  draft: z.boolean().default(false)
});

This simple schema prevented countless potential issues. No more debugging misspelled frontmatter fields or writing defensive code to handle inconsistent data structures. The type system caught these issues before they became runtime problems.

Breaking Free from Framework Lock-in#

I started the migration assuming I’d write everything in React—because that’s just what you do, right? But looking at a simple blog post template, I realized something: I didn’t need React for most of my site.

---
const { title, publishDate, tags } = Astro.props;
---
<article>
  <h1>{title}</h1>
  <time>{publishDate}</time>
  <div class="tags">
    {tags.map(tag => <span class="tag">{tag}</span>)}
  </div>
</article>

Astro’s component syntax was refreshingly simple. For static content, it provided everything I needed without the overhead of a full JavaScript framework.

The Performance Revelation#

While performance wasn’t my initial motivation for switching, Astro’s approach to JavaScript delivery became a game-changer. The concept of Islands Architecture—where interactive components can be selectively hydrated—opened new possibilities:

<CommentSection client:visible />
<NewsletterSignup client:idle />

These directives gave fine-grained control over when and how components load, resulting in significantly smaller initial page loads and better user experience.

Key Learnings from the Migration#

1. Embrace Simplicity#

The “boring” solution is often the right one. Astro’s approach to content management—plain Markdown files in directories—felt almost too simple at first. In practice, it proved more maintainable than complex GraphQL queries.

2. Question Your Assumptions#

We often reach for familiar tools without questioning if they’re the best fit. I didn’t need React for most of my blog posts, and removing it where unnecessary improved performance and simplified maintenance.

3. Type Safety Matters#

Content Collections with TypeScript schemas caught content structure issues that would have silently failed before. This extra layer of safety reduced bugs and improved confidence in content updates.

4. Performance by Default#

Astro’s approach to JavaScript—ship none by default, add only where needed—aligned perfectly with modern performance best practices. The result was faster page loads without sacrificing functionality.

Moving Forward#

This migration taught me valuable lessons about web development that extend beyond just switching frameworks:

  • Simple solutions often scale better than complex ones
  • Framework choices should be driven by requirements, not familiarity
  • Type safety and content validation are worth the upfront investment
  • The best developer experience often leads to the best user experience

If you’re considering a similar migration, start by questioning your assumptions about what you actually need. You might find, as I did, that less is more when it comes to web development tooling.