The `.astro` File

One File, Two Halves — Script and Template

The `.astro` File

An `.astro` file has two parts — a JavaScript frontmatter that runs at build time, and an HTML template that gets rendered.

4 min read Level 1/5 #astro#components#syntax
What you'll learn
  • Recognize the two halves of an `.astro` file
  • Understand what runs where

The .astro file is the building block of an Astro site. It looks like HTML with a JavaScript “preamble” — the script half on top, the template half below.

The Two Halves

---
// 1. Frontmatter script — runs on the SERVER, at build time
const title = "Hello, Astro";
const now = new Date();
---

<!-- 2. HTML template — what the browser actually receives -->
<html>
  <head><title>{title}</title></head>
  <body>
    <h1>{title}</h1>
    <p>Rendered at {now.toLocaleTimeString()}.</p>
  </body>
</html>

The --- fences mark the boundary. Between them is plain TypeScript (or JavaScript). After the closing fence is the template, which can use { ... } to drop values from the script into the HTML.

What Runs Where

Code locationWhen it runsWhere it runs
Frontmatter (--- ... ---)Build / request timeNode (server)
Template { expr }Build / request timeNode (server)
<script> tag in templateRuntimeThe browser
<script is:inline>RuntimeThe browser, untouched
Hydrated framework islandRuntimeThe browser (after JS loads)

The default output is HTML. Browser-side JS only runs when you explicitly opt in via a <script> tag or a hydrated island.

Top-Level await

The frontmatter is async by default — you can await anywhere:

---
const posts = await fetch("https://api.example.com/posts").then(r => r.json());
---

<ul>
  {posts.map(p => <li>{p.title}</li>)}
</ul>

That fetch happens at build time (for static pages) or per-request (for server-rendered pages). Either way, the browser never sees the network call — it just gets HTML.

TypeScript Out of the Box

The frontmatter is TS. Types Just Work:

---
interface Props {
  title: string;
  count?: number;
}
const { title, count = 0 } = Astro.props;
---

<h1>{title}</h1>
<p>Count: {count}</p>

A Component IS a File

There’s no export default function. The whole file is the component. Its props come from Astro.props. Importing it makes it available as a tag:

---
import UserCard from "../components/UserCard.astro";
---

<UserCard name="Ada" />

What’s Next

The next four lessons zoom in on the parts of an .astro file — frontmatter, template, expressions, attributes.

The Frontmatter Script →