Skip to content

Frontmatter Fetch

In Next.js you choose where data runs — getStaticProps (build time), getServerSideProps (per request), or useEffect+fetch (browser). In Astro, the frontmatter --- block IS the data layer. Top-level await fetch() there runs at build time by default, or per-request if the page opts into SSR. No useEffect, no browser fetch.

Build-time fetch: getStaticProps vs frontmatter

Section titled “Build-time fetch: getStaticProps vs frontmatter”
React
// pages/blog.tsx (Next.js Pages Router)
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return { props: { posts } };
}
export default function Blog({ posts }) {
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
Astro
---
// src/pages/blog.astro (Astro — static by default)
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
---
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>

With Astro’s default static output, this await fetch() runs once at build time — exactly like getStaticProps. The result is baked into static HTML, zero fetching at runtime.

Per-request fetch: getServerSideProps vs SSR frontmatter

Section titled “Per-request fetch: getServerSideProps vs SSR frontmatter”
React
// pages/dashboard.tsx (Next.js Pages Router)
export async function getServerSideProps(context) {
const res = await fetch(
`https://api.example.com/user/${context.params.id}`
);
const user = await res.json();
return { props: { user } };
}
export default function Dashboard({ user }) {
return <h1>Hello, {user.name}</h1>;
}
Astro
---
// src/pages/dashboard.astro (Astro SSR mode)
export const prerender = false; // opt into SSR
const userId = Astro.url.searchParams.get('id');
const res = await fetch(`https://api.example.com/user/${userId}`);
const user = await res.json();
---
<h1>Hello, {user.name}</h1>

export const prerender = false opts this single page into SSR — every request re-runs the frontmatter. The rest of your site stays static.

Astro
---
// Swap this for: const res = await fetch('https://...'); const posts = await res.json();
const posts = [
  { id: 1, title: "Why Astro ships zero JS by default", date: "2024-01-10" },
  { id: 2, title: "Content collections vs contentlayer", date: "2024-02-03" },
  { id: 3, title: "Islands: hydrate only what you need", date: "2024-03-15" },
];
---
<html lang="en">
  <head><meta charset="utf-8" /><title>Blog</title></head>
  <body style="font-family:sans-serif;padding:2rem">
    <h1>Latest Posts</h1>
    <ul style="list-style:none;padding:0">
      {posts.map((post) => (
        <li style="margin:1rem 0;padding:1rem;border:1px solid #e2e8f0;border-radius:8px">
          <strong>{post.title}</strong>
          <span style="display:block;color:#718096;font-size:0.875rem">{post.date}</span>
        </li>
      ))}
    </ul>
  </body>
</html>
When does `await fetch()` in Astro frontmatter run by default?
What is the Astro equivalent of Next.js `getStaticProps`?
How do you make an Astro page fetch data per-request (like `getServerSideProps`)?