Skip to content

ADR-013: BaseLayout Slot Strategy for Hero and CTA Sections

Accepted

The BaseLayout.astro component currently uses a single default <slot /> for page content. A suggestion was raised to add named slots for hero and CTA sections to provide more structured extensibility. However, this raises questions about:

  • Whether BaseLayout should dictate specific content patterns (hero/CTA)
  • How to maintain flexibility for diverse page layouts
  • The balance between structure and coupling
  • Consistency with Astro’s composition patterns
  • Separation of Concerns: BaseLayout should handle document structure (HTML, head, body), not content patterns
  • Flexibility: Pages should compose their own content structure without layout constraints
  • Atomic Design Principles: Content sections (hero, CTA) are organisms/templates, not layout concerns
  • Zero-JS Performance: Avoid unnecessary layout complexity that could impact performance
  • Developer Experience: Minimize cognitive load and maximize composability

Option 1: Add named slots for hero and CTA sections

Section titled “Option 1: Add named slots for hero and CTA sections”
<BaseLayout>
<slot name="hero" slot="hero" />
<main>
<slot />
</main>
<slot name="cta" slot="cta" />
</BaseLayout>

Pros:

  • Explicit structure for common patterns
  • Could enforce consistent hero/CTA placement

Cons:

  • Couples layout to specific content patterns
  • Reduces flexibility for non-standard page layouts
  • Violates single responsibility principle (layout vs. content structure)
  • Adds complexity for pages that don’t need hero/CTA
  • Hero/CTA are content concerns, not layout concerns

Option 2: Keep single default slot (current approach)

Section titled “Option 2: Keep single default slot (current approach)”
<BaseLayout>
<main>
<slot />
</main>
</BaseLayout>

Pros:

  • Maximum flexibility for page composition
  • Clear separation: BaseLayout = document structure, pages = content structure
  • Simpler mental model
  • Aligns with Astro’s composition philosophy
  • Pages can use Section components to build any structure

Cons:

  • No enforced structure for hero/CTA placement
  • Developers must understand Section-based composition

Option 3: Create specialized layout variants

Section titled “Option 3: Create specialized layout variants”

Create HeroLayout.astro, CTALayout.astro that extend BaseLayout.

Pros:

  • Provides structured options without forcing them
  • Could be useful for very specific page types

Cons:

  • Layout proliferation
  • Still couples layout to content patterns
  • Adds maintenance burden
  • Unclear when to use which layout

Option 2 is chosen: Keep single default slot in BaseLayout.

BaseLayout.astro will continue to provide only document-level structure:

  • HTML document setup
  • Head management (via Head component)
  • Body structure with Header, main, Footer
  • Theme setup and accessibility features

Content structure is the responsibility of pages, which compose their layouts using:

  • Section.astro for semantic sections
  • Container.astro for content width constraints
  • Organism components for complex patterns (hero, CTA, etc.)

This approach:

  1. Maintains separation of concerns: BaseLayout = document, pages = content
  2. Maximizes flexibility: Any page can compose any structure
  3. Follows Atomic Design: Hero/CTA are organisms composed within pages
  4. Aligns with Astro patterns: Single slot is the Astro-idiomatic approach
  5. Simplifies maintenance: One layout to maintain, not multiple variants
  • Clear responsibility boundaries: BaseLayout handles document, pages handle content
  • Maximum composability: Pages can create any structure using Section/Container
  • Simpler codebase: No layout variants to maintain
  • Better DX: Single pattern to learn (compose with Section components)
  • Performance: No unnecessary layout complexity
  • Documentation: Must clearly document the composition pattern
    • Add examples showing hero/CTA composition in pages
    • Document Section/Container usage patterns
    • Show how to build common page structures
  • Component library: Ensure organism-level components exist for common patterns
    • Consider HeroSection.astro organism if pattern repeats
    • Consider CTASection.astro organism if pattern repeats
    • Keep these as organisms, not layout concerns
  • No enforced structure: Developers must understand composition patterns
    • Mitigated by: Clear documentation and examples
    • Mitigated by: Existing pages as reference implementations
<BaseLayout title="..." description="...">
<!-- Page composes its own structure -->
<Section><!-- Hero --></Section>
<Section><!-- Content --></Section>
<Section><!-- CTA --></Section>
</BaseLayout>

Create organism components, not layout slots:

src/components/organisms/HeroSection.astro
<Section class="hero-specific-styles">
<Container>
<slot />
</Container>
</Section>
<!-- Usage in pages -->
<BaseLayout>
<HeroSection>
<h1>Title</h1>
<p>Description</p>
</HeroSection>
</BaseLayout>
  • ✅ BaseLayout maintains single default slot
  • ✅ Pages compose structure using Section/Container
  • ✅ No layout variants created without ADR justification
  • ✅ Documentation includes composition examples
  • ✅ Code reviews enforce separation of layout vs. content concerns
  • Testable consequences:
    • TC-1: src/layouts/BaseLayout.astro defines no named slots.
  • Checks:
    • TC-1 → check baselayout-no-named-slots (status: warn)
  • Not machine-checkable: whether a page composes hero/CTA sections appropriately is a review concern.
  • Graduation log: (empty at creation; entries added when a check changes status)

Date: 2025-10-01 (footer backfilled 2026-07-05 from git history; this record predates the footer convention)
Participants: Template maintainers
Outcome: Accepted