BaseLayout
BaseLayout.astro is the root layout component that wraps every page in the framework. It provides the HTML shell, head meta tags, and slot structure for navbar, content, and footer.
Location
File: src/layouts/BaseLayout.astro
Role in the Stack
┌─────────────────────────────────────────────────────────────┐
│ BaseLayout.astro │
│ │
│ <html> │
│ <head> │
│ • Meta tags (title, description, OG) │
│ • Favicon │
│ • Font preconnects │
│ • Theme flash prevention script │
│ </head> │
│ <body> │
│ ┌─────────────────────────────────────────────────┐ │
│ │ <slot name="navbar" /> ← Navbar component │ │
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ <main> │ │
│ │ <slot /> ← Content layout (docs/blog/custom) │ │
│ │ </main> │ │
│ └─────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ <slot name="footer" /> ← Footer component │ │
│ └─────────────────────────────────────────────────┘ │
│ </body> │
│ </html> │
│ │
└─────────────────────────────────────────────────────────────┘
Props Interface
interface BaseLayoutProps {
title: string; // Page title (required)
description?: string; // Meta description
ogImage?: string; // Open Graph image URL
}
Structure
---
import { loadSiteConfig, getFavicon } from '@loaders/config';
import '@/styles/globals.css';
interface Props {
title: string;
description?: string;
ogImage?: string;
}
const { title, description, ogImage } = Astro.props;
const siteConfig = loadSiteConfig();
const faviconUrl = getFavicon();
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- SEO -->
<title>{title} | {siteConfig.site.name}</title>
<meta name="description" content={description || siteConfig.site.description} />
<!-- Open Graph -->
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
{ogImage && <meta property="og:image" content={ogImage} />}
<!-- Favicon -->
<link rel="icon" href={faviconUrl} />
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<!-- Theme Flash Prevention -->
<script is:inline>
// Runs before page renders to prevent flash
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', theme);
</script>
</head>
<body>
<slot name="navbar" />
<main class="main-content">
<slot />
</main>
<slot name="footer" />
</body>
</html>
Slot System
BaseLayout uses Astro's named slots for composition:
| Slot | Purpose | Filled By |
|---|---|---|
navbar |
Top navigation | NavbarStyle1, NavbarMinimal |
| (default) | Main content | Layout components |
footer |
Bottom footer | FooterDefault, FooterMinimal |
Usage in Page Components
---
// In [...slug].astro
import BaseLayout from '@layouts/BaseLayout.astro';
import NavbarStyle1 from '@layouts/navbar/style1/index.astro';
import FooterDefault from '@layouts/footer/default/index.astro';
import DocsLayout from '@layouts/docs/styles/doc_style1/Layout.astro';
---
<BaseLayout title={title} description={description}>
<NavbarStyle1 slot="navbar" />
<DocsLayout {...layoutProps} />
<FooterDefault slot="footer" />
</BaseLayout>
Dark Mode Handling
The inline script prevents theme flash on page load:
// Runs synchronously before render
const theme = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-theme', theme);
This sets data-theme attribute immediately, before CSS loads, preventing the flash of wrong theme colors.
CSS uses the attribute for theming:
:root {
--color-bg: #ffffff;
--color-text: #1a1a1a;
}
[data-theme="dark"] {
--color-bg: #1a1a1a;
--color-text: #ffffff;
}
Flex Layout Structure
The body uses flexbox for sticky footer:
body {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.main-content {
flex: 1; /* Grows to fill available space */
}
This ensures:
- Navbar stays at top
- Footer stays at bottom (even on short pages)
- Content fills the middle
Favicon Resolution
Favicon is loaded from site configuration:
// In BaseLayout
import { getFavicon } from '@loaders/config';
const faviconUrl = getFavicon();
// getFavicon() reads from site.yaml
// logo:
// favicon: "@assets/favicon.png" → /assets/favicon.png
Global Styles Import
BaseLayout imports the global stylesheet:
---
import '@/styles/globals.css';
---
This file contains:
- CSS reset
- CSS custom properties (colors, spacing, typography)
- Base element styles
- Dark mode variables