Getting Started with Astro - Part 2: Components and Content
Learn how to create reusable components in Astro and manage content with Markdown and data fetching capabilities.
Astro Get Started
Part 2 of 3
Building with Astro Components
In Part 1, we covered the basics of Astro and set up our first project. Now, let’s dive deeper into one of Astro’s most powerful features: components.
Astro components are the building blocks of your website. They’re files with a .astro
extension that contain reusable pieces of HTML, CSS, and JavaScript. Unlike components in frameworks like React or Vue, Astro components render to HTML at build time by default, resulting in zero JavaScript sent to the browser.
Anatomy of an Astro Component
An Astro component has two main parts:
- Component Script (optional) - A JavaScript code fence (
---
) containing component logic - Component Template - HTML markup with expressions for dynamic content
---
// Component Script (runs at build time)
const title = "My Astro Component";
const items = ["Item 1", "Item 2", "Item 3"];
// You can import other components
import Button from "./Button.astro";
// Or even import from other frameworks
import ReactCounter from "../components/ReactCounter.jsx";
---
<!-- Component Template (HTML with expressions) -->
<div class="my-component">
<h2>{title}</h2>
<ul>
{items.map((item) => (
<li>{item}</li>
))}
</ul>
<Button text="Click me" />
<!-- Use client:* directives for interactive components -->
<ReactCounter client:load />
</div>
<style>
.my-component {
border: 1px solid #ccc;
padding: 1rem;
margin-bottom: 1rem;
}
h2 {
color: navy;
}
</style>
Props and Dynamic Data
Astro components can accept props, making them truly reusable:
---
// Define the props your component accepts
const { title, color = "blue" } = Astro.props;
---
<h2 style={`color: ${color};`}>{title}</h2>
You can then use this component in another .astro
file:
---
import Heading from "../components/Heading.astro";
---
<Heading title="Welcome to my site" color="purple" />
<Heading title="Another heading" /> <!-- Uses default color -->
Working with Content in Astro
Markdown and MDX Support
Astro has excellent support for Markdown content, making it perfect for blogs and documentation sites. Files placed in the src/pages/
directory with .md
extensions automatically become pages on your site.
Here’s an example of a Markdown file in Astro:
---
# This is frontmatter - metadata for your content
title: My First Blog Post
publishDate: 2023-10-27
author: Dragos
---
# {frontmatter.title}
This is my first blog post! It was published on {new Date(frontmatter.publishDate).toLocaleDateString()}.
## Markdown Features
- **Bold text** and *italic text*
- [Links](https://astro.build)
- Lists and more!
You can enhance your Markdown with MDX (requires the MDX integration) to use components within your content:
npm install @astrojs/mdx
Then update your astro.config.mjs
:
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
});
Content Collections
Astro 2.0+ introduced Content Collections, a powerful way to manage your Markdown and MDX content:
src/content/
├── blog/
│ ├── post-1.md
│ └── post-2.md
└── authors/
├── author-1.md
└── author-2.md
Define a schema for your collections in src/content/config.ts
:
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
schema: z.object({
title: z.string(),
publishDate: z.date(),
author: z.string(),
tags: z.array(z.string()).optional(),
}),
});
export const collections = {
'blog': blogCollection,
};
Then query your content in your Astro components:
---
import { getCollection } from 'astro:content';
// Get all blog posts
const allBlogPosts = await getCollection('blog');
// Sort by publish date
const sortedPosts = allBlogPosts.sort(
(a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime()
);
---
<h1>My Blog</h1>
<ul>
{sortedPosts.map(post => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<p>Published on {post.data.publishDate.toLocaleDateString()}</p>
</li>
))}
</ul>
Data Fetching in Astro
Astro allows you to fetch data from external sources during the build process:
---
// Fetch data at build time
const response = await fetch('https://api.example.com/data');
const data = await response.json();
// Process the data
const items = data.items.slice(0, 5); // Get first 5 items
---
<h2>Latest Items</h2>
<ul>
{items.map(item => (
<li>
<h3>{item.title}</h3>
<p>{item.description}</p>
</li>
))}
</ul>
Server Endpoints
You can create API endpoints in Astro by adding .js
or .ts
files to the src/pages/
directory:
// src/pages/api/items.json.js
export async function get() {
// Fetch or generate data
const data = {
items: [
{ id: 1, title: 'Item 1' },
{ id: 2, title: 'Item 2' },
{ id: 3, title: 'Item 3' },
]
};
return {
body: JSON.stringify(data),
};
}
This creates an endpoint at /api/items.json
that returns JSON data.
Styling in Astro
Astro offers several ways to style your components:
Scoped Styles
Styles defined within an Astro component are automatically scoped to that component:
<style>
/* These styles only apply to this component */
h1 {
color: purple;
font-size: 2rem;
}
</style>
Global Styles
For global styles, you can create a styles file and import it in your layout:
---
// src/layouts/MainLayout.astro
import '../styles/global.css';
---
<html>
<!-- Layout content -->
</html>
CSS Frameworks
Astro works well with CSS frameworks like Tailwind CSS. To add Tailwind:
npm install -D @astrojs/tailwind tailwindcss
Update your astro.config.mjs
:
import { defineConfig } from 'astro/config';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
integrations: [tailwind()],
});
Conclusion
In this second part of our Astro series, we’ve explored components, content management with Markdown and MDX, data fetching, and styling options. These features make Astro a powerful tool for building content-focused websites.
Astro’s component model gives you the flexibility to build reusable UI elements while maintaining excellent performance. The built-in support for Markdown and content collections makes it easy to manage blog posts, documentation, and other content types.
In Part 3, we’ll cover deployment, optimization, and advanced features to take your Astro site to the next level.
Want to review the basics? Head back to Part 1: Introduction and Setup. Ready for more advanced topics? Continue to Part 3: Deployment and Advanced Features.
Related Posts
Getting Started with Modern Web Development
Learn the fundamentals of modern web development with this comprehensive guide covering HTML, CSS, JavaScript, and popular frameworks.
Getting Started with Astro - Part 3: Deployment and Advanced Features
Learn how to deploy your Astro site, optimize performance, and leverage advanced features for production-ready websites.
Mobile App Development Guide
Learn the essentials of mobile app development, including native vs cross-platform approaches, popular frameworks, and best practices.