Mastering Astro Web Development
Astro Component Architecture
The Astro Component
At the heart of every Astro project is the Astro component. These files, ending with a .astro extension, are a superset of HTML. They feel familiar, yet they have superpowers. An Astro component is made of two main parts: a code fence and a component template.
Astro is a web framework for content-driven sites.
Think of the code fence as the component's brain. It's a section at the top of the file, fenced off by --- markers. All the JavaScript you write inside this fence runs on the server, never in the user's browser. This is where you can import other components, fetch data from an API, or define variables to use in your template.
// src/components/Greeting.astro
---
// This is the code fence. It's all JavaScript.
const name = "World";
---
<!-- This is the component template. It's mostly HTML. -->
<h1>Hello, {name}!</h1>
The component template is the body of the component, living outside the code fence. This is where you write your HTML structure. You can use standard HTML tags, other Astro components, and even components from frameworks like React or Vue. The most important thing to remember is that by default, it all renders down to plain, static HTML. There's no client-side JavaScript unless you explicitly ask for it.
This zero-JS-by-default approach is what makes Astro sites incredibly fast.
Passing Data with Props
Components aren't very useful if they're completely static. You need a way to pass data into them. In Astro, this is done with Astro.props. You can define the props a component expects inside the code fence and then access them to make your component dynamic.
To make our Greeting component reusable, we can pull the name out into a prop. With TypeScript, you can even define the shape of your props for better type safety and editor autocompletion.
// src/components/Greeting.astro
---
interface Props {
name: string;
}
const { name } = Astro.props;
---
<h1>Hello, {name}!</h1>
Now, you can use this Greeting component elsewhere and pass it different names. This is the core of building reusable UI elements.
<!-- src/pages/index.astro -->
---
import Greeting from '../components/Greeting.astro';
---
<html lang="en">
<head>
<title>My Astro Site</title>
</head>
<body>
<Greeting name="Astro" />
<Greeting name="Developer" />
</body>
</html>
Scoped Styles and Content
Styling in modern web development can be tricky. Global stylesheets often lead to class name collisions and unpredictable results. Astro solves this by scoping CSS by default. Any styles you write in a <style> tag inside an .astro file only apply to the HTML in that same file.
<!-- src/components/Greeting.astro -->
---
const { name } = Astro.props;
---
<h1>Hello, {name}!</h1>
<style>
h1 {
color: rebeccapurple;
font-family: sans-serif;
}
</style>
The h1 style defined here won't leak out and affect any other <h1> elements on your site. Astro achieves this by adding a unique hash as an attribute to the elements and rewriting the CSS selector to target it. It's a powerful feature that lets you write simple CSS without worrying about side effects.
For passing content into a component, Astro uses a special <slot /> element. This acts as a placeholder where a parent component can inject its own markup. This is a common pattern for creating layouts.
Imagine a BaseLayout component that defines the overall page structure, including the <html>, <head>, and <body> tags. You can use a <slot /> to mark where the unique content for each page should go. This keeps your code (Don't Repeat Yourself).
<!-- src/layouts/BaseLayout.astro -->
---
const { title } = Astro.props;
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{title}</title>
</head>
<body>
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
<main>
<slot /> <!-- Page content will be injected here -->
</main>
</body>
</html>
Then, on a specific page, you wrap your content in the BaseLayout component, and it automatically gets placed into the slot.
<!-- src/pages/about.astro -->
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="About Me">
<h2>My name is Astro.</h2>
<p>I live on the server and send HTML to your browser.</p>
</BaseLayout>
This combination of props for data and slots for content provides a flexible and powerful system for building complex user interfaces from small, understandable pieces. Astro's architecture lets you bring in interactive components from other frameworks, but only hydrates them when needed, a concept known as . This gives you the performance of a static site with the dynamic capabilities of a full-fledged app.
Hydration
noun
The process of taking a server-rendered HTML page and making it interactive in the browser by attaching JavaScript event listeners.
Now that you understand the basic building blocks, let's review what we've learned.
Ready to test your knowledge?
What are the two main parts of an Astro component file (.astro)?
Where does the JavaScript written inside the code fence (---) of an Astro component execute?
Mastering the Astro component is the first step toward building fast, content-focused websites. By separating server-side logic from the template and scoping styles automatically, Astro provides a developer experience that is both simple and powerful.