Skip to content

Content & Data

In React you fetch data with getServerSideProps, getStaticProps, or useEffect+fetch. In Astro, data lives in the frontmatter --- block — it runs at build time or on the server — or in content collections, which give you type-safe MD/MDX management. Zero browser-side fetching by default.

LessonWhat you’ll learn
Frontmatter Fetchawait fetch() in frontmatter vs getServerSideProps
Content CollectionsdefineCollection + zod schema vs contentlayer
Rendering Markdownrender(entry) vs MDX in Next
Dynamic from DatagetStaticPaths() from a collection
React
// pages/blog.tsx (Next.js)
import { useEffect, useState } from 'react';
export default function Blog() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://api.example.com/posts')
.then(r => r.json())
.then(setPosts);
}, []);
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
Astro
---
// src/pages/blog.astro
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
---
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>

Notice: in Astro, await fetch() sits directly in the frontmatter. It runs at build time (static) or per-request (SSR). No useEffect, no loading state, no client-side JavaScript shipped for the fetch itself.

Astro
---
// In a real project, replace this array with await fetch(...) in the frontmatter
const posts = [
  { id: 1, title: "Getting started with Astro" },
  { id: 2, title: "Content collections deep dive" },
  { id: 3, title: "Islands architecture explained" },
];
---
<html lang="en">
  <head><meta charset="utf-8" /><title>Posts</title></head>
  <body style="font-family:sans-serif;padding:2rem">
    <h1>Blog Posts</h1>
    <ul>
      {posts.map((post) => (
        <li style="margin:0.5rem 0">{post.title}</li>
      ))}
    </ul>
  </body>
</html>
Where does data fetching code run in an Astro component?
Which Astro feature provides type-safe MD/MDX content management?
Does Astro ship data-fetching JavaScript to the browser by default?