Layouts
Layouts
Section titled “Layouts”The astro-basics project provides flexible layout components that support both standard page structures and advanced customization through Astro’s slot pattern.
Available Layouts
Section titled “Available Layouts”Base Layout
Section titled “Base Layout”The foundational layout that all other layouts extend. Includes navigation, header area, and footer.
Location: src/layouts/Base.astro
Features:
- Customizable header via slots
- Optional header visibility control
- SEO meta tags
- Authentication integration
---import Base from '#layouts/Base.astro'---
<Base pageTitle="Page Title" pageDescription="Page description" pageImageUrl="/images/hero.jpg" hideHeader={false}> <!-- Page content --></Base>Main Layout
Section titled “Main Layout”Extends Base with a main content area and sidebar.
Location: src/layouts/Layout.astro
Use cases: Blog posts, documentation pages, content-rich pages
---import Layout from '#layouts/Layout.astro'---
<Layout pageTitle="Blog Post" showBreadcrumb={true}> <!-- Main content -->
<aside slot="sidebar"> <!-- Sidebar content --> </aside></Layout>Auth Layout
Section titled “Auth Layout”Simplified layout for authentication pages.
Location: src/layouts/Auth.astro
Use cases: Login, register, password reset pages
---import Auth from '#layouts/Auth.astro'---
<Auth pageTitle="Sign In" hideHeader={true}> <!-- Auth form content --></Auth>Custom Headers
Section titled “Custom Headers”One of the most powerful features is the ability to customize page headers using Astro’s named slot pattern.
Using the Default Header
Section titled “Using the Default Header”The default header automatically uses pageTitle and pageDescription props:
<Base pageTitle="Welcome to My Site" pageDescription="Discover amazing content"> <!-- Content --></Base>Providing a Custom Header
Section titled “Providing a Custom Header”Use the header slot to provide any custom component:
---import Base from '#layouts/Base.astro'import CustomHero from '#components/astro/CustomHero.astro'---
<Base pageTitle="Landing Page"> <CustomHero slot="header" title="Big Announcement" subtitle="Something exciting is coming" backgroundImage="/hero-bg.jpg" />
<!-- Page content --></Base>Hiding the Header
Section titled “Hiding the Header”For pages that don’t need a header (like authentication pages):
<Base hideHeader={true}> <!-- Content without header --></Base>Common Patterns
Section titled “Common Patterns”Landing Page with Custom Hero
Section titled “Landing Page with Custom Hero”---import Base from '#layouts/Base.astro'import HeroSection from '#components/astro/HeroSection.astro'---
<Base pageTitle="Product Launch"> <HeroSection slot="header" headline="Transform Your Workflow" subheadline="The tools you need to succeed" ctaText="Get Started" ctaLink="/signup" backgroundImage="/hero.jpg" />
<section> <!-- Feature sections --> </section></Base>Marketing Page with Promo Header
Section titled “Marketing Page with Promo Header”---import Base from '#layouts/Base.astro'import PromoHeader from '#components/astro/PromoHeader.astro'
const promoActive = true---
<Base pageTitle="Special Offer"> {promoActive && ( <PromoHeader slot="header" message="Limited Time: 50% Off All Plans" ctaText="Claim Offer" expiresAt="2025-12-31" /> )}
<!-- Marketing content --></Base>Blog Post with Featured Image Header
Section titled “Blog Post with Featured Image Header”---import Layout from '#layouts/Layout.astro'import FeaturedImageHeader from '#components/astro/FeaturedImageHeader.astro'
const post = Astro.props.post---
<Layout pageTitle={post.title}> <FeaturedImageHeader slot="header" image={post.heroImage} title={post.title} author={post.author} publishDate={post.pubDate} readingTime={post.readingTime} />
<article> <!-- Blog post content --> </article></Layout>Dashboard with Minimal Header
Section titled “Dashboard with Minimal Header”---import Auth from '#layouts/Auth.astro'import DashboardHeader from '#components/dashboard/DashboardHeader.astro'
const user = Astro.locals.user---
<Auth pageTitle="Dashboard"> <DashboardHeader slot="header" userName={user.name} lastLogin={user.lastLogin} notifications={5} />
<!-- Dashboard content --></Auth>Layout Props Reference
Section titled “Layout Props Reference”Base Layout Props
Section titled “Base Layout Props”type Props = { pageTitle?: string // Page title for <title> and default header pageDescription?: string // Meta description and header subtitle pageImageUrl?: string // OG image and header background showBreadcrumb?: boolean // Show/hide breadcrumb navigation breadcrumbRoutes?: Array<{ // Custom breadcrumb items name: string url: string path?: string }> hideHeader?: boolean // Hide header completely}Named Slots
Section titled “Named Slots”All layouts support these named slots:
| Slot Name | Purpose | Available In |
|---|---|---|
header |
Custom header component | Base, Layout, Auth |
sidebar |
Sidebar content | Layout |
featured |
Featured content area | Layout |
| Default slot | Main page content | All layouts |
Best Practices
Section titled “Best Practices”1. Choose the Right Layout
Section titled “1. Choose the Right Layout”<!-- Content pages with sidebar --><Layout pageTitle="Article">...</Layout>
<!-- Landing pages, marketing --><Base pageTitle="Home">...</Base>
<!-- Auth pages, dashboards --><Auth pageTitle="Login">...</Auth>2. Use Path Aliases
Section titled “2. Use Path Aliases”Always use the # alias for imports:
// ✅ Correctimport Base from '#layouts/Base.astro'import Header from '#components/astro/Header.astro'
// ❌ Avoidimport Base from '../layouts/Base.astro'import Header from '../components/astro/Header.astro'3. Consistent SEO Props
Section titled “3. Consistent SEO Props”Always provide title and description for better SEO:
<Base pageTitle="Unique Page Title - Site Name" pageDescription="Descriptive text for search engines and social media" pageImageUrl="/og-images/page-specific.jpg"> <!-- Content --></Base>4. Accessibility in Custom Headers
Section titled “4. Accessibility in Custom Headers”Ensure custom headers maintain semantic structure:
---export type Props = { title: string subtitle?: string}
const { title, subtitle } = Astro.props---
<header role="banner" aria-label="Page header"> <div class="header-container"> <h1 id="page-title">{title}</h1> {subtitle && ( <p class="header-subtitle">{subtitle}</p> )} </div></header>5. Performance with Client Components
Section titled “5. Performance with Client Components”If using React components as custom headers, choose appropriate hydration:
<!-- Static: No JS needed --><StaticHeader slot="header" />
<!-- Interactive: Load immediately --><InteractiveHeader slot="header" client:load />
<!-- Interactive: Load when visible --><InteractiveHeader slot="header" client:visible />
<!-- Interactive: Load when browser idle --><InteractiveHeader slot="header" client:idle />Creating Custom Layouts
Section titled “Creating Custom Layouts”To create a new layout that extends Base:
---import Base from './Base.astro'
export type Props = { pageTitle?: string customProp?: string hideHeader?: boolean}
const { pageTitle, customProp, hideHeader } = Astro.props---
<Base pageTitle={pageTitle} hideHeader={hideHeader}> {/* Forward header slot to Base */} {Astro.slots.has('header') && ( <slot name="header" slot="header" /> )}
<div class="custom-layout"> {/* Custom layout structure */} <slot /> </div></Base>
<style> .custom-layout { /* Custom styling */ }</style>Examples
Section titled “Examples”Simple Content Page
Section titled “Simple Content Page”---import Base from '#layouts/Base.astro'---
<Base pageTitle="About Us" pageDescription="Learn about our story"> <section> <h2>Our Story</h2> <p>Content...</p> </section></Base>Blog Post with Sidebar
Section titled “Blog Post with Sidebar”---import Layout from '#layouts/Layout.astro'import TableOfContents from '#components/astro/TableOfContents.astro'
const post = Astro.props---
<Layout pageTitle={post.title} pageDescription={post.excerpt} showBreadcrumb={true}> <article> {/* Post content */} </article>
<TableOfContents slot="sidebar" headings={post.headings} /></Layout>Authentication Page
Section titled “Authentication Page”---import Auth from '#layouts/Auth.astro'import { SignIn } from '@clerk/astro/components'---
<Auth pageTitle="Sign In" hideHeader={true}> <section class="auth-container"> <h2>Welcome Back</h2> <SignIn /> </section></Auth>Related Documentation
Section titled “Related Documentation”- Components - Available header components
- Styling - Layout styling and theming
- Custom Header Slots - Detailed header customization guide (project-docs)
Migration Notes
Section titled “Migration Notes”From Previous Versions
Section titled “From Previous Versions”The slot-based header feature is fully backward compatible. No changes needed for existing pages:
<!-- ✅ Works: Existing code --><Base pageTitle="Old Page"> <p>Content</p></Base>
<!-- ✅ Works: New feature, opt-in --><Base pageTitle="New Page"> <CustomHeader slot="header" /> <p>Content</p></Base>Upgrading from Static Headers
Section titled “Upgrading from Static Headers”If you were working around header limitations:
<!-- Before: Workaround with hideHeader --><Base hideHeader={true}> <CustomHeader /> {/* Not in slot */} <main> <p>Content</p> </main></Base>
<!-- After: Proper slot usage --><Base> <CustomHeader slot="header" /> <p>Content</p></Base>