Skip to main content

Overview

Layouts are special Astro components that provide reusable page templates. They wrap page content and provide consistent structure across the site. Proyecto Renacer uses a single main layout: Layout.astro.

Layout Location

Layouts are stored in /src/layouts/:
src/
└── layouts/
    └── Layout.astro

Layout.astro - Main Layout

The primary layout template used by all pages.

Full Component Code

src/layouts/Layout.astro
---
import "../styles/global.css";
import Head from "../components/Head.astro";
import OpenGraph from "../components/OpenGraph.astro";

const { title, description, image, OGTitle, OGDescription, OGImage } =
  Astro.props;
---

<!doctype html>
<html lang="es">
  <head>
    <!-- meta -->
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />

    <!-- title -->
    <title>{title}</title>
    
    <!-- Analytics -->
    <script
      src="https://analytics.ahrefs.com/analytics.js"
      data-key="sASfd12IOBxOqgA/S0QsDQ"
      async></script>
    
    <!-- Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700;800;900&display=swap"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght@100..700,0..1&display=swap"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap"
      rel="stylesheet"
    />

    <meta name="description" content={description} />

    <!-- robots -->
    <meta name="robots" content="index,follow" />
    
    <!-- SEO components -->
    <Head />
    
    <OpenGraph
      OGTitle={OGTitle ?? title}
      OGDescription={OGDescription ?? description}
      OGImage={OGImage ?? image}
    />
  </head>
  <body
    class="bg-light font-display text-slate-900 dark:text-slate-100 dark:bg-dark"
  >
    <slot />
  </body>
</html>

<style>
  html,
  body {
    margin: 0;
    width: 100%;
    height: 100%;
  }

  body {
    font-family: "Public Sans", sans-serif;
  }
  .material-symbols-outlined {
    font-variation-settings:
      "FILL" 0,
      "wght" 400,
      "GRAD" 0,
      "opsz" 24;
  }
</style>

Layout Structure

The layout is divided into several key sections:

1. Frontmatter (Props)

---
import "../styles/global.css";
import Head from "../components/Head.astro";
import OpenGraph from "../components/OpenGraph.astro";

const { title, description, image, OGTitle, OGDescription, OGImage } =
  Astro.props;
---
Imports:
  • Global CSS styles
  • SEO components (Head, OpenGraph)
Props:
  • title - Page title for <title> tag
  • description - Meta description for SEO
  • image - Default social sharing image
  • OGTitle - Optional custom Open Graph title
  • OGDescription - Optional custom OG description
  • OGImage - Optional custom OG image

2. HTML Structure

<!doctype html>
<html lang="es">
  <head>
    <!-- Head content -->
  </head>
  <body>
    <slot />
  </body>
</html>
Key elements:
  • lang="es" - Spanish language attribute
  • <head> - Meta tags, fonts, analytics
  • <body> - Container for page content
  • <slot /> - Placeholder for page content

3. Head Section

The <head> contains several important elements:

Meta Tags

<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<meta name="description" content={description} />
<meta name="robots" content="index,follow" />

Title

<title>{title}</title>
Dynamically set from page props.

Analytics

<script
  src="https://analytics.ahrefs.com/analytics.js"
  data-key="sASfd12IOBxOqgA/S0QsDQ"
  async></script>
Ahrefs analytics integration.

Fonts

Two Google Fonts are loaded:
  1. Public Sans - Main typography
<link
  href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700;800;900&display=swap"
  rel="stylesheet"
/>
  1. Material Symbols - Icon font
<link
  href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght@100..700,0..1&display=swap"
  rel="stylesheet"
/>

SEO Components

<Head />

<OpenGraph
  OGTitle={OGTitle ?? title}
  OGDescription={OGDescription ?? description}
  OGImage={OGImage ?? image}
/>
Uses nullish coalescing (??) to fall back to default props if custom OG values aren’t provided.

4. Body

<body
  class="bg-light font-display text-slate-900 dark:text-slate-100 dark:bg-dark"
>
  <slot />
</body>
Tailwind classes:
  • bg-light - Light background color
  • font-display - Custom font family
  • text-slate-900 - Dark text color
  • dark:text-slate-100 - Light text in dark mode
  • dark:bg-dark - Dark background in dark mode
Slot: The <slot /> is where page content is injected.

5. Scoped Styles

<style>
  html,
  body {
    margin: 0;
    width: 100%;
    height: 100%;
  }

  body {
    font-family: "Public Sans", sans-serif;
  }
  
  .material-symbols-outlined {
    font-variation-settings:
      "FILL" 0,
      "wght" 400,
      "GRAD" 0,
      "opsz" 24;
  }
</style>
Reset styles:
  • Remove default margins
  • Set 100% dimensions
Font configuration:
  • Apply Public Sans font family
  • Configure Material Symbols icon appearance

Using the Layout

Pages import and wrap their content with the layout:
src/pages/index.astro
---
import Layout from "../layouts/Layout.astro";
import Header from "../components/Header.astro";
import Footer from "../components/Footer.astro";

const title = "Proyecto Renacer | Vivienda Social en Ambato";
const description = "Descripción de la página para SEO...";
---

<Layout title={title} description={description}>
  <Header />
  <main>
    <!-- Page content here -->
  </main>
  <Footer />
</Layout>

With Custom Open Graph Tags

---
const title = "Page Title";
const description = "Page description";
const OGTitle = "Custom social share title";
const OGImage = "/images/custom-share-image.jpg";
---

<Layout 
  title={title} 
  description={description}
  OGTitle={OGTitle}
  OGImage={OGImage}
>
  <!-- Content -->
</Layout>

Layout Props Reference

title
string
required
Page title displayed in browser tab and search results
description
string
required
Meta description for SEO (150-160 characters recommended)
image
string
Default social sharing image URL
OGTitle
string
Custom Open Graph title (falls back to title if not provided)
OGDescription
string
Custom Open Graph description (falls back to description if not provided)
OGImage
string
Custom Open Graph image (falls back to image if not provided)

Dark Mode Support

The layout includes dark mode support via Tailwind’s dark: variant:
<body
  class="bg-light dark:bg-dark text-slate-900 dark:text-slate-100"
>
How it works:
  • Light mode: bg-light and text-slate-900
  • Dark mode: dark:bg-dark and dark:text-slate-100
  • Triggered by system preference or custom toggle

Global CSS

The layout imports global styles:
import "../styles/global.css";
This file contains:
  • Tailwind base, components, and utilities
  • Custom CSS variables for colors
  • Global reset styles

Font Loading Strategy

Fonts are loaded from Google Fonts CDN:
<link
  href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700;800;900&display=swap"
  rel="stylesheet"
/>
Features:
  • display=swap - Prevents FOIT (Flash of Invisible Text)
  • Multiple weights loaded (300-900)
  • Async loading for performance

SEO Architecture

The layout provides comprehensive SEO coverage:
1

Basic Meta Tags

Charset, viewport, description, and robots directives
2

Dynamic Title

Page-specific titles from props
3

Head Component

Favicon, generator tag, and additional meta tags
4

Open Graph Tags

Social media sharing optimization via OpenGraph component

Analytics Integration

Ahrefs analytics is integrated at the layout level:
<script
  src="https://analytics.ahrefs.com/analytics.js"
  data-key="sASfd12IOBxOqgA/S0QsDQ"
  async></script>
Benefits:
  • Loaded once for all pages
  • Async loading for performance
  • Automatic page view tracking

Best Practices

These are required props for proper SEO:
<Layout title="..." description="...">
The layout provides the shell; pages should use semantic tags:
<Layout>
  <Header />
  <main>
    <article>...</article>
  </main>
  <Footer />
</Layout>
Recommended size: 1200x630px for best social media display
Meta descriptions should be 150-160 characters for optimal display in search results

Creating Additional Layouts

If you need specialized layouts:
1

Create new layout file

touch src/layouts/BlogLayout.astro
2

Extend base layout

---
import Layout from "./Layout.astro";
const { title, author, date } = Astro.props;
---

<Layout title={title}>
  <article>
    <header>
      <h1>{title}</h1>
      <p>By {author} on {date}</p>
    </header>
    <slot />
  </article>
</Layout>
3

Use in pages

---
import BlogLayout from "../layouts/BlogLayout.astro";
---

<BlogLayout title="Post" author="Name" date="2024-01-01">
  Content here
</BlogLayout>

Next Steps

Pages

See how layouts are used in pages

Components

Learn about Head and OpenGraph components

Overview

Return to project structure overview