Data Fetching & API Endpoints
There are three genuinely different ways to get data into an Astro site, each with its own timing and tradeoffs.
Fetching in the Frontmatter: Build Time, Not Request Time
fetch() call happens at build time in Astro's default static output mode — the response gets baked directly into the pre-rendered HTML. If the API's own data changes afterward, the site won't reflect it until the next build and deploy. This isn't a bug to work around; it's the same static-by-default model already established, just applied to a network request instead of a plain variable.
API Endpoints
Any file in src/pages/api/ exporting a named GET (or POST, PUT, etc.) function returning a real Response becomes a working API endpoint — here, reachable at /api/posts.json. In static output mode, this endpoint is also generated once at build time, the same constraint as the frontmatter fetch above; Chapter 10's server/hybrid modes are what let an endpoint like this run fresh on every request instead.
Client-Side Fetching Inside an Island
A hydrated island (Chapter 7) can fetch data itself, in the browser, at runtime — genuinely fresh every time the component loads, regardless of when the site was last built. The real cost is exactly what Chapter 7 already established: this requires shipping and hydrating real client-side JavaScript, unlike the frontmatter fetch's zero-JS static output.
Three Approaches, Compared
| Approach | Runs When | Ships JS? | Data Freshness |
|---|---|---|---|
Frontmatter fetch() | Build time, once | No | Frozen until next build |
| API endpoint (static mode) | Build time, once | No (unless called from an island) | Frozen until next build |
| Client-side fetch in an island | Every time the component loads, in the browser | Yes | Always current |
Coding Challenges
Fetch data from a public placeholder API inside a page's frontmatter, render it as a list, then rebuild the site and confirm the rendered output only changes on a fresh build, not on every page load.
📄 View solutionBuild a src/pages/api/posts.json.ts endpoint returning a hard-coded JSON array via a GET function, and confirm it's reachable directly by visiting /api/posts.json.
📄 View solutionBuild a client-side-fetching island (client:load) that fetches from your own /api/posts.json endpoint at runtime, and explain how this differs from Challenge 1's frontmatter-fetch approach.
📄 View solutionChapter 9 Quick Reference
- Frontmatter
fetch()— runs once at build time, result frozen into static HTML src/pages/api/*.ts— a namedGET/POSTexport returning aResponsebecomes a real endpoint- Both are static in default mode — Chapter 10's server/hybrid modes remove this constraint
- Client-side fetch in an island — always fresh, but requires shipping real JavaScript
- Next chapter: Rendering Modes: Static, Server & Hybrid