Imagine you have 10 pages on your site. Each page needs:
<head> sectionBad approach: Copy-paste this code on every page.
Layouts are components that wrap your page content. You define the common structure ONCE, then reuse it everywhere.
Frame = Layout (stays same)
Picture = Content (changes)
Header/Footer = Layout
Letter content = Your page
Foundation/Walls = Layout
Furniture = Your content
Put it in src/layouts/
src/layouts/BaseLayout.astro <slot />The <slot /> is where your page content goes
<!-- Layout structure -->
<header>Nav here</header>
<main>
<slot /> <!-- Page content goes here -->
</main>
<footer>Footer here</footer> Import and use the layout on your pages
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout>
<h1>My Page Content</h1>
<p>This goes in the slot!</p>
</BaseLayout>
Astro takes your page content and inserts it where the
<slot /> is in the layout!
<slot /> <slot /> is a placeholder
for your page content.
<!-- BaseLayout.astro -->
<html>
<body>
<nav>Navigation</nav>
<main>
<slot /> <!-- Content goes here -->
</main>
<footer>Footer</footer>
</body>
</html> <!-- about.astro -->
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout>
<h1>About Page</h1>
<p>This is the about page content.</p>
</BaseLayout> <html>
<body>
<nav>Navigation</nav>
<main>
<h1>About Page</h1>
<p>This is the about page content.</p>
</main>
<footer>Footer</footer>
</body>
</html>
💡 The <h1> and <p> from your page
replaced the <slot /> in the layout!
Just like components, layouts can receive props to customize behavior.
<!-- BaseLayout.astro -->
---
const { title, description } = Astro.props;
---
<html>
<head>
<title>{title}</title>
<meta name="description" content={description} />
</head>
<body>
<main>
<slot />
</main>
</body>
</html> <!-- about.astro -->
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="About Me"
description="Learn about my creative journey"
>
<h1>About Page Content</h1>
</BaseLayout> title - Page titledescription - Meta description for SEOogImage - Social media preview imageclass - Custom CSS class for the pageDifferent sections of your site might need different layouts.
For regular pages (home, about, contact)
For blog posts
For portfolio projects
You can wrap a layout inside another layout!
BaseLayout (HTML structure, nav, footer)
└─ BlogLayout (blog-specific features)
└─ Your blog post content <!-- BaseLayout.astro -->
<html>
<body>
<nav>Nav</nav>
<slot /> <!-- BlogLayout goes here -->
<footer>Footer</footer>
</body>
</html>
<!-- BlogLayout.astro -->
---
import BaseLayout from './BaseLayout.astro';
---
<BaseLayout>
<article>
<div class="blog-meta">Date, Author, etc.</div>
<slot /> <!-- Blog post content goes here -->
</article>
</BaseLayout>
<!-- my-blog-post.astro -->
---
import BlogLayout from '../layouts/BlogLayout.astro';
---
<BlogLayout>
<h1>My Post</h1>
<p>Content here</p>
</BlogLayout> 💡 This creates layers: BaseLayout wraps BlogLayout wraps your content!
Layouts should handle structure, not complex logic
BaseLayout, BlogLayout, ProjectLayout (clear purpose)
Standard convention, easy to find
Let pages customize titles, descriptions, etc.
Layouts should work for multiple pages
2-3 levels max, or it gets confusing
| Feature | Layout | Component |
|---|---|---|
| Purpose | Wrap entire pages | Reusable UI pieces |
Uses <slot /> | Yes (usually) | Sometimes |
| Location | src/layouts/ | src/components/ |
Contains <html> | Usually yes | Usually no |
| Examples | Page structure, nav, footer | Button, Card, Modal |
| Used per page | One per page | Multiple per page |
Layout = Page wrapper (structure)
Component = Reusable UI element (content)
src/
├── layouts/
│ ├── BaseLayout.astro (HTML, nav, footer)
│ └── ProjectLayout.astro (For project pages)
├── components/
│ ├── Nav.astro (Navigation bar)
│ ├── Footer.astro (Footer)
│ └── ProjectCard.astro (Project preview card)
└── pages/
├── index.astro (Uses BaseLayout)
├── about.astro (Uses BaseLayout)
└── projects/
├── project-1.astro (Uses ProjectLayout)
└── project-2.astro (Uses ProjectLayout)