Runs Once, on the Server, Before the Page Goes Out
The Frontmatter Script
Whatever lives between the two `---` fences runs at build time or per request — never in the browser. Use it to fetch data, import components, and compute values.
What you'll learn
- Use the frontmatter to import and compute
- Use `await` for build-time data fetching
- Read props and request info from `Astro`
Everything between the two --- fences is server-side
TypeScript / JavaScript. It runs once per page render — at
build time for static pages, per request for SSR. The browser never
sees it.
Three Common Things
1. Import components and helpers
---
import Header from "../components/Header.astro";
import { formatDate } from "../lib/dates.ts";
--- 2. Fetch and compute
---
const res = await fetch("https://api.example.com/posts");
const posts = await res.json();
const featured = posts.filter(p => p.featured);
--- 3. Read props and the request
---
interface Props {
title: string;
}
const { title } = Astro.props;
const path = Astro.url.pathname;
--- The Astro Global
The frontmatter has access to an Astro object with everything
about the current render. The most useful fields:
| Field | What it is |
|---|---|
Astro.props | Props passed to this component |
Astro.params | URL params for dynamic routes (e.g. [slug]) |
Astro.url | A URL instance — pathname, searchParams, etc. |
Astro.request | The full Request (server pages only) |
Astro.cookies | Read/write cookies |
Astro.redirect | Redirect to another URL |
Astro.slots | Programmatic access to slot content |
No Browser APIs
The frontmatter runs in Node — window, document, localStorage
don’t exist there. If you need them, put the code in a <script>
tag in the template (or inside an island).
Top-Level Await
The frontmatter is an async context — await works without
wrapping anything:
---
const data = await fetch(...).then(r => r.json());
const html = await marked.parse(data.markdown);
--- Imports Anywhere
import only works in the frontmatter. The template half can’t
have its own imports. Anything you want to render must be imported
above the closing fence.
Up Next
After the script — the template.
The HTML Template →