Data, content, and assets

Load data before rendering

Use top-level await in frontmatter and know whether the work happens during a build or an on-demand request.

8 minute lesson

~~~

An Astro component can await data before it produces HTML:

---
const response = await fetch("https://api.example.com/products")

if (!response.ok) {
  throw new Error(`Product request failed: ${response.status}`)
}

const products = await response.json()
---

<ul>
  {products.map(product => <li>{product.name}</li>)}
</ul>

There is no client-side loading state here. Astro waits for the fetch, renders the list, and sends the resulting HTML.

The important question is when the route renders. A static route fetches during astro build. Its data stays in the generated page until the next build. This is fast and resilient for visitors, but a price change in the API will not appear automatically.

An on-demand route fetches on the server for a request. Its data can be fresher, but visitors now depend on the API and your server response time.

Choose based on how stale the page may safely be. Then handle failures explicitly: check response.ok, decide whether the build should stop, and avoid silently publishing an empty page when an upstream service fails.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →