Basics of Astro

What Is Astro?

Astro is a web framework for building fast websites.

Main idea:

Create a Project

pnpm create astro@latest
cd my-site
pnpm install
pnpm dev

Default dev server:

http://localhost:4321

Project Structure

my-site/
├── public/
├── src/
│   ├── components/
│   ├── layouts/
│   └── pages/
├── astro.config.mjs
└── package.json

Pages

Files in src/pages/ become routes.

src/pages/
├── index.astro
├── about.astro
└── blog/
    └── hello.astro

Routes:

/
/about
/blog/hello

Astro Components

Astro components use .astro files.

---
const name = "Marvin";
---

<h1>Hello {name}</h1>

The --- section is the frontmatter. It runs on the server/build side by default.

Components

src/components/Header.astro:

<header>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>
</header>

Use it:

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

<Header />

<h1>Home</h1>

Props

---
const { title } = Astro.props;
---

<h1>{title}</h1>

Use it:

<Card title="Hello" />

Layouts

Layouts let you reuse page structure.

---
const { title } = Astro.props;
---

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>{title}</title>
  </head>
  <body>
    <slot />
  </body>
</html>

Use it:

---
import Layout from "../layouts/Layout.astro";
---

<Layout title="Home">
  <h1>Hello</h1>
</Layout>

<slot /> is where the page content goes.

CSS

<style>
  h1 {
    color: red;
  }
</style>

<h1>Hello</h1>

Astro scopes component styles by default.

JavaScript

Astro does not send component JavaScript to the browser by default.

Browser-side JavaScript:

<button id="button">Click me</button>

<script>
  document.querySelector("#button")?.addEventListener("click", () => {
    alert("Hello");
  });
</script>

UI Frameworks

Astro can use React, Vue, Svelte, and other UI frameworks.

For example:

pnpm astro add react

Then:

---
import Counter from "../components/Counter.jsx";
---

<Counter client:load />

Client Directives

They control when framework components become interactive.

<Component client:load />

Load immediately.

<Component client:idle />

Load when the browser is idle.

<Component client:visible />

Load when the component becomes visible.

<Component client:only="react" />

Render only on the client.

Dynamic Routes

Create:

src/pages/blog/[slug].astro
---
const { slug } = Astro.params;
---

<h1>{slug}</h1>

For /blog/hello:

slug = "hello"

Rendering Lists

---
const posts = [
  { title: "First", slug: "first" },
  { title: "Second", slug: "second" },
];
---

{posts.map((post) => (
  <a href={`/blog/${post.slug}`}>
    {post.title}
  </a>
))}

API Endpoints

Create:

src/pages/api/hello.ts
export function GET() {
  return new Response(JSON.stringify({ message: "Hello" }), {
    headers: {
      "Content-Type": "application/json",
    },
  });
}

The endpoint is available at:

/api/hello

Static Assets

Put static files in public/:

public/logo.png

Use them with:

<img src="/logo.png" alt="Logo" />

Environment Variables

PUBLIC_API_URL=https://example.com
SECRET_KEY=secret

Public variables use the PUBLIC_ prefix:

---
const apiUrl = import.meta.env.PUBLIC_API_URL;
---

Keep secrets server-side.

Build Commands

pnpm dev
pnpm build
pnpm preview

The Big Idea

Default Astro:

Astro component

    HTML

   browser

Interactive component:

Astro

React / Vue / Svelte

HTML + JavaScript

Astro tries to ship HTML by default and JavaScript only when needed.

Learn Next

  1. Pages and routing
  2. Components
  3. Props
  4. Layouts
  5. Content collections
  6. Dynamic routes
  7. API endpoints
  8. Server-side rendering
  9. Client directives
  10. Deployment