Skip to content

Frontmatter & Template

A React component has two logical sections: the function body (where you declare variables, call hooks, and run logic) and the returned JSX (what renders). An Astro component mirrors this split with an explicit fence.

---
// frontmatter: JS/TS that runs at build or server time
---
<!-- template: HTML-first markup rendered to static HTML -->

The --- pair is called the component script or frontmatter. Everything between the fences is plain TypeScript/JavaScript. Everything after the closing --- is the template — an HTML superset where you can embed expressions with {...}.

Think of the frontmatter as the top of a React function, minus hooks and event handlers. You can:

  • Import other components, utilities, and data files.
  • Fetch data with await (the entire component runs on the server/build).
  • Destructure props from Astro.props.
  • Declare local variables that the template reads.
React
// Card.jsx (function body = "frontmatter")
import { formatDate } from './utils';
export default function Card({ title, date }) {
// runs in the browser on every render
const formatted = formatDate(date);
return (
<div className="card">
<h2>{title}</h2>
<time>{formatted}</time>
</div>
);
}
Astro
---
// Card.astro (frontmatter = component script)
import { formatDate } from './utils';
// runs ONCE at build time — never in the browser
const { title, date } = Astro.props;
const formatted = formatDate(date);
---
<div class="card">
<h2>{title}</h2>
<time>{formatted}</time>
</div>

After the closing --- you write HTML. It is not JSX:

  • Use class not className.
  • Boolean attributes work the standard HTML way.
  • Self-closing tags follow HTML rules (but Astro is lenient — both <img /> and <img> work).
  • Embed any JavaScript expression with {expr}.
Astro
---
const items = ["Astro", "React", "TypeScript"];
const hero = { title: "Welcome", subtitle: "Zero JS by default" };
---
<html lang="en">
  <head><meta charset="utf-8" /><title>{hero.title}</title></head>
  <body>
    <h1>{hero.title}</h1>
    <p>{hero.subtitle}</p>
    <ul>
      {items.map((item) => <li>{item}</li>)}
    </ul>
  </body>
</html>
Where would you write `const data = await fetch('/api/posts')` in an Astro component?
Which attribute name is correct in an Astro HTML template?
Can you call React hooks like useState inside an Astro frontmatter block?
What is the closing delimiter of the Astro frontmatter block?