We explore the main advantages of Astro as a modern framework for building static and dynamic websites.
Astro is a modern framework that is transforming the way we build websites. In this article we explore the main advantages that make it an excellent choice for your projects.
What is Astro?
Astro is a framework for building ultra-fast static websites. Unlike other frameworks, Astro implements an islands-based architecture, which means it only loads the JavaScript needed by the client.
---
// An Astro component ships no JS to the client by default
const title = "My fast site";
const author = "Andrés Puello";
---
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>By {author}</p>
</body>
</html>
Astro project structure
A typical project has this structure:
src/ ├── components/ │ ├── ui/ # Reusable components │ ├── layout/ # Shared layouts │ └── sections/ # Page sections ├── content/ # Content collections │ ├── projects/ │ └── blog/ ├── layouts/ # Astro layouts ├── pages/ # Site routes │ ├── index.astro │ ├── blog/ │ │ └── [slug].astro │ └── projects/ │ └── [slug].astro └── styles/ # Global styles
Astro components: the basics
Astro components are .astro files with a TypeScript frontmatter and an HTML template.
---
// Typed props
interface Props {
name: string;
times?: number;
}
const { name, times = 1 } = Astro.props;
const items = Array.from({ length: times }, (_, i) => i + 1);
---
<div class="greeting">
<h2>Hello, {name}!</h2>
<ul>
{items.map((i) => (
<li>Greeting #{i}</li>
))}
</ul>
</div>
<style>
.greeting {
color: tomato;
}
</style>
Slots: content composition
Slots let you inject child content into a component, similar to children in React.
---
interface Props {
title: string;
description?: string;
}
const { title, description = "My website" } = Astro.props;
---
<html lang="en">
<head>
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
<footer>
<slot name="footer" />
</footer>
</body>
</html>
--- import BaseLayout from "../layouts/BaseLayout.astro"; --- <BaseLayout title="Home" description="Main page"> <h1 slot="header">Welcome</h1> <p>Main content of the page.</p> <small slot="footer">© 2025</small> </BaseLayout>
Main advantages
1. Superior performance
Astro automatically removes unnecessary JavaScript on the client side, resulting in faster sites and better scores on Core Web Vitals metrics.
By default, an Astro component renders to static HTML on the server. Only when you use directives like
client:loadorclient:visibledoes JavaScript hydrate on the client.
2. Compatibility with multiple frameworks
You can use components from React, Vue, Svelte, Solid and other frameworks within the same Astro project.
--- import Counter from "../components/Counter.tsx"; // This is an interactive "island" --- <section> <h2>My counter</h2> <Counter client:visible /> </section>
3. Islands-based architecture
This architecture allows you to load only the interactive parts of the page, keeping the rest as static HTML.
4. Powerful integrations
Astro has a large number of integrations available for CMS, analytics tools, and more.
# Add official integrations npx astro add react npx astro add tailwind npx astro add mdx npx astro add sitemap
Data fetching at build time
Astro runs getStaticPaths at build time to generate dynamic pages:
---
import { getCollection } from "astro:content";
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.data.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<article>
<h1>{post.data.title}</h1>
<Content />
</article>
Conclusion
Astro represents a paradigm shift in modern web development, offering a hybrid solution that combines the best of static sites and dynamic web applications.