Basics of Astro
What Is Astro?
Astro is a web framework for building fast websites.
Main idea:
- HTML first
- Minimal JavaScript
- Components when needed
- Supports React, Vue, Svelte, etc.
- Great for content-heavy sites
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
- Pages and routing
- Components
- Props
- Layouts
- Content collections
- Dynamic routes
- API endpoints
- Server-side rendering
- Client directives
- Deployment