Learning Astro - Pages, Layouts & Components
Episode 4 of 24

Learning Astro - Pages, Layouts & Components

This episode builds the Astro UI foundation: creating pages in src/pages, reusable layouts with slots in src/layouts, Astro components with props and frontmatter, the difference between framework components, and styling with global CSS, scoped styles, and Tailwind.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

After the project is ready from episode 3, it is time to build the main building blocks of the site: pages, layouts, and components. These three are the UI foundation of Astro — almost everything you build in this series comes down to these three concepts.

Pages define routes, layouts wrap many pages with a shared skeleton, and components are reusable pieces of UI. Combining them with tidy styling produces a site that is consistent and easy to maintain.

Episode 4 is full practice: you will create your first page, a reusable layout, components with props, and then try styling with plain CSS, scoped styles, and Tailwind.

Creating Pages in src/pages

The First Static Page

Every .astro file in src/pages becomes a route. Create src/pages/tentang.astro for the /tentang page:

JSHalaman statis sederhana
---
const namaSitus = "Astro Learn";
---
 
<html lang="id">
  <head>
    <title>Tentang Kami</title>
  </head>
  <body>
    <h1>Halo, selamat datang di {namaSitus}</h1>
    <p>Halaman ini dirender sebagai HTML murni saat build.</p>
  </body>
</html>

Frontmatter (between ---) contains JavaScript that runs at build time. The value of {namaSitus} is interpolated into the template — you will use this interpolation pattern over and over.

Dynamic Pages with Parameters

For dynamic pages like article detail pages, use brackets in the file name:

JSHalaman dinamis [slug].astro
---
export function getStaticPaths() {
  return [
    { params: { slug: "satu" } },
    { params: { slug: "dua" } },
  ];
}
 
const { slug } = Astro.params;
---
 
<h1>Artikel: {slug}</h1>

getStaticPaths produces the list of static pages to be built — each item in the array becomes one HTML file in dist/.

Reusable Layouts with src/layouts

Creating a Base Layout

A layout is a special component that wraps page content. Create src/layouts/Base.astro:

JSLayout Base dengan slot
---
interface Props {
  title: string;
}
const { title } = Astro.props;
---
 
<html lang="id">
  <head>
    <title>{title}</title>
  </head>
  <body>
    <nav>Logo | Beranda | Blog | Kontak</nav>
    <main>
      <slot />
    </main>
    <footer>Hak cipta 2026</footer>
  </body>
</html>

The <slot /> element is a marker where the page content will be inserted. Props are received through Astro.props and declared with interface Props.

Using a Layout in a Page

Use the layout by importing and wrapping the page:

JSHalaman memakai layout
---
import Base from "../layouts/Base.astro";
---
 
<Base title="Beranda">
  <h1>Beranda</h1>
  <p>Konten halaman masuk ke slot layout.</p>
</Base>

A layout saves a lot of duplicated code — the title, meta tags, navigation, and footer only need to be written once.

Astro Components and Framework Components

Astro Components with Props

.astro components are pieces of UI without page-level HTML. Example src/components/Card.astro:

JSKomponen Card
---
interface Props {
  judul: string;
  deskripsi: string;
}
const { judul, deskripsi } = Astro.props;
---
 
<article class="card">
  <h2>{judul}</h2>
  <p>{deskripsi}</p>
</article>

This component can be used anywhere with <Card judul="Astro" deskripsi="Cepat" />. The --- fence above the script defines the boundary between frontmatter logic and the HTML template.

Framework Components as Islands

React, Vue, Svelte, and Solid components can also be used in .astro files. The difference: those components are interactive and need a hydration directive for their JavaScript to be shipped. Astro components themselves do not need a directive — they are always rendered as static HTML unless used as an island with a directive.

Styling with CSS, Scoped Styles, and Tailwind

Global CSS and Scoped Styles

Global CSS goes in src/styles and is imported in layouts. For styles that only apply to one component, Astro provides scoped styles:

JSScoped style di komponen
<style>
  .card {
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 1rem;
  }
</style>

Astro automatically adds a unique hash to the selectors in a <style> block, so .card will not leak into other components.

Tailwind CSS

Tailwind can be enabled with a single integration command:

Menambahkan Tailwind
npx astro add tailwind

npx astro add tailwind installs the package and configures Vite. After that, utility classes can be used directly across all templates, including inside .astro files and framework components.

Tip

The most common combination: the layout holds global CSS and meta tags, small components use scoped styles or Tailwind utility classes, and pages simply assemble everything.

Conclusion

Episode 4 builds the three UI foundations of Astro: pages in src/pages in static and dynamic modes, reusable layouts with slots, Astro components with props, and styling through global CSS, scoped styles, and Tailwind.

The key takeaways:

  • Every file in src/pages becomes a route, static or dynamic.
  • getStaticPaths determines the list of dynamic pages at build time.
  • Layouts use <slot /> and accept props like title.
  • Astro components render statically without JavaScript.
  • <style> blocks in components are automatically scoped.
  • npx astro add tailwind enables Tailwind in a single command.

In the next episode 5, we will cover content and markdown: writing content with Markdown and MDX, leveraging content collections with schemas, frontmatter and metadata, and rendering dynamic content on static pages. This is the heart of a content-driven site.