Table of contents
Open Table of contents
The Situation
I needed to rebuild my blog. The previous setup – a combination of WordPress and various plugins – had become unwieldy. Page loads were slow, maintenance was a chore, and I was spending more time fighting the platform than writing content.
I wanted something different: fast, simple to maintain, and optimised for what a blog actually needs to do – serve content quickly and get out of the way.
The Challenge
Most modern JavaScript frameworks come with a fundamental problem for content sites: they ship too much JavaScript. React, Vue, Next.js – they’re brilliant for interactive applications, but for a blog where 90% of pages are essentially static content, sending hundreds of kilobytes of JavaScript to render text feels… wrong.
I’d tried static site generators before (Hugo, Jekyll), but they came with their own friction – templating languages I didn’t enjoy, limited flexibility when I did need interactivity, and build processes that felt disconnected from modern frontend development.
The Lesson
The breakthrough came when I discovered Astro’s core philosophy: ship zero JavaScript by default.
Astro renders everything to static HTML at build time. Interactive components only get hydrated when explicitly requested. The result? Pages that load almost instantly because they’re just HTML and CSS until proven otherwise.
Here’s what that looks like in practice:
---
// This JavaScript runs at build time, not in the browser
const posts = await getCollection('blog');
const recentPosts = posts.slice(0, 5);
---
<ul>
{recentPosts.map(post => (
<li><a href={`/posts/${post.slug}`}>{post.data.title}</a></li>
))}
</ul>
No JavaScript shipped. Just HTML. For a blog index page, that’s exactly right.
When I do need interactivity – say, a search component – I can bring in a React or Vue component and explicitly tell Astro to hydrate it:
---
import SearchWidget from '../components/SearchWidget.jsx';
---
<SearchWidget client:load />
Only that component gets JavaScript. The rest of the page stays static.
The Tactic
If you’re considering Astro for a content site, here’s my practical advice:
Start with content collections. Astro’s content collections feature handles Markdown/MDX processing beautifully. Define your schema once, get type safety throughout your templates. My blog posts are just MDX files in a folder, and Astro handles the rest.
Use Azure Static Web Apps for hosting. The integration is seamless – push to GitHub, automatic builds and deploys. I literally push content and walk away. The GitHub Actions workflow configures itself.
Don’t fight the islands architecture. Astro’s “islands” model (static by default, interactive components as islands) requires a mental shift if you’re coming from React/Next.js. Embrace it. Most of your content doesn’t need JavaScript.
Leverage the ecosystem. Astro has excellent integrations for Tailwind, MDX, RSS feeds, sitemaps. Use them rather than building custom solutions.
Results
Since switching to Astro:
- Lighthouse scores: Consistent 95+ across all metrics
- Build times: Under 30 seconds for ~50 posts
- Maintenance burden: Nearly zero – it just works
- Time to publish: Write MDX, push to GitHub, done
The framework genuinely gets out of the way and lets me focus on content. That’s exactly what I wanted.
Conclusion
Astro isn’t the right choice for every project. If you’re building a highly interactive application, React or Vue (possibly with Next.js or Nuxt) makes more sense. But for content-focused sites – blogs, documentation, marketing pages – it’s become my default recommendation.
The performance-first philosophy, combined with the flexibility to use any framework components when genuinely needed, strikes a balance I haven’t found elsewhere. Give it a look if you’re building something similar.