Hello, I'm Maneshwar. I'm working on FreeDevTools online currently building *one place for all dev tools, cheat codes, and TLDRs* — a free, open-source hub where developers can quickly find and use tools without any hassle of searching all over the internet.
Astro has quickly become a favorite for developers building fast, SEO-optimized static sites.
At the core of its performance and flexibility lie Astro components — the building blocks of every Astro project.
If you’ve ever written HTML, you already know the basics of Astro components.
Let’s walk through what they are, how they work, and why they make Astro so powerful for static site generation (SSG).
What Are Astro Components?
Astro components are .astro
files that combine HTML templates with server-side logic.
Unlike typical JavaScript frameworks, they don’t ship any JavaScript to the browser by default.
Every Astro component is pre-rendered into HTML — either at build time or on-demand — meaning your users get instant page loads without waiting for hydration or runtime JavaScript.
That’s what makes Astro sites blazingly fast.
Why Astro Components Are Different
When you use React, Vue, or Svelte, components render on the client side using JavaScript. Astro flips that model — it renders components on the server, stripping away JS before the page is sent to the browser.
If you need interactivity, you can still opt-in using client islands — interactive UI components that load separately using directives like:
<MyReactComponent client:visible />
This lets you build partially interactive pages without sacrificing static-site performance.
Anatomy of an Astro Component
Each .astro
file has two sections:
---
// Component Script (server-side)
---
<!-- Component Template (HTML + JS expressions) -->
1. Component Script
This section runs only on the server. You can:
- Import other Astro or framework components
- Load data from APIs or local files
- Use variables and props
Example:
---
import SomeReactComponent from '../components/SomeReactComponent.jsx';
const { title } = Astro.props;
const data = await fetch('https://api.example.com/items').then(r => r.json());
---
Everything inside this block is safe — even private API calls — since none of it ever reaches the client.
2. Component Template
Below the code fence, you define your HTML output.
You can mix in JavaScript expressions and imported components:
---
const { title } = Astro.props;
const items = ['Astro', 'React', 'Vue'];
---
<h1>{title}</h1>
<ul>
{items.map(name => <li>{name}</li>)}
</ul>
When the site builds, this turns into pure HTML.
Component-Based Design
Astro’s component model is fully composable.
You can create small building blocks (like Button.astro
) and reuse them to form complex UIs.
Example:
---
import Button from './Button.astro';
---
<div>
<Button title="Button 1" />
<Button title="Button 2" />
</div>
This makes large static sites easier to maintain and scale.
Passing Data with Props
Props in Astro work like other frameworks — they pass data into components.
---
// GreetingHeadline.astro
const { greeting = "Hello", name = "World" } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
Usage:
<GreetingHeadline greeting="Hi" name="Astro" />
You can also define a TypeScript interface for prop validation:
---
interface Props {
name: string;
greeting?: string;
}
const { greeting = "Hello", name } = Astro.props;
---
Slots: Flexible Layouts & Content
Slots let you pass HTML content into a component — similar to React’s children
.
Example:
---
// Wrapper.astro
const { title } = Astro.props;
---
<div>
<h1>{title}</h1>
<slot />
</div>
Usage:
<Wrapper title="About Astro">
<p>Astro components render to static HTML.</p>
</Wrapper>
Named Slots
You can create multiple placeholders inside a component:
<slot name="header" />
<slot />
<slot name="footer" />
And pass them in like:
<Wrapper>
<h1 slot="header">Header Area</h1>
<p>Main content</p>
<footer slot="footer">Footer Area</footer>
</Wrapper>
This enables reusable layouts where child content is dynamically inserted into specific regions.
Fallback Slots
Slots can also include fallback content:
<slot>
<p>This content appears if no slot is provided.</p>
</slot>
This ensures your components always render gracefully, even when no child content is passed in.
Nested Layouts and Slot Transfer
Astro supports nested layouts using slot transfer.
For example, you can have a BaseLayout
and HomeLayout
:
<!-- BaseLayout.astro -->
<html>
<head>
<slot name="head" />
</head>
<body>
<slot />
</body>
</html>
<!-- HomeLayout.astro -->
<BaseLayout>
<slot name="head" slot="head" />
<slot />
</BaseLayout>
Now, you can reuse layout layers without duplicating structure — perfect for complex static sites.
HTML Components
Astro can even import plain .html
files as components.
These are pure HTML, with no frontmatter or scripting, making them ideal for legacy or fully static sections.
Why This Matters for Static Site Generation
Astro components are optimized for static output. Every .astro
file becomes HTML during build time — meaning:
- No client-side rendering overhead
- No hydration until you explicitly ask for it
- Better SEO, smaller bundles, faster TTFB
Astro’s approach gives you the simplicity of static sites with the flexibility of modern frameworks.
Final Thoughts
Astro components redefine how we think about building for the web.
They combine the speed of static HTML, the modularity of components, and the power of selective interactivity — making them ideal for large, content-heavy sites.
If you’re building a blog, docs site, or an icon library with 100k+ pages, Astro’s component model is built for that scale.
I’ve been building for FreeDevTools.
A collection of UI/UX-focused tools crafted to simplify workflows, save time, and reduce friction in searching tools/materials.
Any feedback or contributors are welcome!
It’s online, open-source, and ready for anyone to use.
👉 Check it out: FreeDevTools
⭐ Star it on GitHub: freedevtools
Top comments (0)