Skip to content

Pages, Routing & Components

Pages and components are the building blocks of any website. In this chapter, we’ll cover how to create pages using Astro’s file-based routing, how to build reusable components with props, and how to use layouts and slots to avoid repeating code. We’ll also look at how to handle images, create a navbar and footer, and set up a custom 404 page for when users visit a non-existent URL.

Astro uses file-based routing. This simply means: whatever file you create inside the pages folder automatically becomes a page on your website, based on its name and location.

src/pages/
├─ index.astro -> /
├─ about.astro -> /about
├─ blog/
│ ├─ index.astro -> /blog
│ └─ [slug].astro -> /blog/my-post

So, index.astro always becomes your homepage (/), and any file inside a folder becomes a page under that folder’s path.

A file name wrapped in square brackets, like [slug].astro, means this page can handle many different URLs, depending on the value of slug.

// src/pages/blog/[slug].astro
export async function getStaticPaths() {
return [
{ params: { slug: "hello-world" } }
];
}

In simple words: getStaticPaths() tells Astro every possible value slug can have, so Astro knows exactly which pages to generate ahead of time.

Every Astro component file starts with a section between two --- lines. This is called the frontmatter, or the component script.

---
const title = "Hello Astro";
const isLoggedIn = true;
---
<h1>{title}</h1>
  • This code runs at build time, not in the browser.
  • You cannot use browser-only things here, like window or document.
  • Think of this section as running in a Node.js environment, similar to backend code.

Layouts help you avoid repeating the same HTML structure (like header, footer, or <head> tags) on every single page.

---
// src/layouts/BaseLayout.astro
const { title } = Astro.props;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<slot />
</body>
</html>

The <slot /> tag is like a placeholder. Whatever content you put inside the layout when you use it, gets dropped into that exact spot.

---
import BaseLayout from "../layouts/BaseLayout.astro";
---
<BaseLayout title="Home">
<h1>Home Page</h1>
</BaseLayout>

Sometimes you want more than one “placeholder” spot in your layout. That’s what named slots are for.

<slot name="footer" />

Here’s how you’d fill that named slot when using the layout:

<BaseLayout title="About">
<fragment slot="footer">
<footer>© 2023 Your Site Name. All rights reserved.</footer>
</fragment>
</BaseLayout>

Props are just values you pass into a component, similar to how you’d pass attributes to an HTML tag.

---
// Card.astro
const { title = "Default Title", description } = Astro.props;
---
<h2>{title}</h2>
<p>{description}</p>

Using the component:

<Card title="Astro" description="Fast & SEO friendly" />

If you’re using TypeScript, you can clearly mark which props are required and which are optional.

---
const { title, description } = Astro.props;
interface Props {
title: string;
description?: string;
}
// here title is required but description is optional
---

Note: Before using TypeScript interfaces like this, run npx astro add typescript and then npx astro sync first.

A good habit here is:

  • Keep these components simple, without extra state.
  • Don’t add JavaScript to them unless you really need to.
<nav>
<a href="/">Home</a>
<a href="/blog">Blog</a>
</nav>

Place components like this inside your layout file, not repeated inside every single page.

Astro gives you a built-in <Image /> component to handle images in a smart, optimized way.

  • It resizes images automatically.
  • It loads images lazily (only when they’re about to appear on screen), which saves loading time.
  • It can convert images to modern formats like WebP or AVIF, which are smaller in size.
---
import { Image } from "astro:assets";
import hero from "../assets/hero.png";
---
<Image src={hero} alt="Hero image" width={800} />

Good habits to follow:

  • Always add an alt text (this describes the image, and helps with both accessibility and SEO).
  • Prefer using local images (stored inside your project) over linking to images from other websites.

You can create your own “Page Not Found” page like this:

---
// src/pages/404.astro
---
<h1>404 - Page Not Found</h1>

Astro automatically picks this file up and shows it whenever someone visits a page that doesn’t exist.