Layouts Explained

Layouts are wrapper components that provide shared UI across multiple pages - like headers, footers, and navigation. They ensure consistency and reduce code duplication.

What is a Layout?

A layout wraps your page content with shared elements.

Without layout (repetitive):

// Every page repeats this:
function AboutPage() {
  return (
    <>
      <Header />
      <main>About content</main>
      <Footer />
    </>
  )
}

function ContactPage() {
  return (
    <>
      <Header />
      <main>Contact content</main>
      <Footer />
    </>
  )
}

With layout (DRY - Don't Repeat Yourself):

// Layout (once)
function DefaultLayout({ children }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  )
}

// Pages (simple)
function AboutPage() {
  return <DefaultLayout>About content</DefaultLayout>
}

function ContactPage() {
  return <DefaultLayout>Contact content</DefaultLayout>
}

Our Layout System

We have several layouts for different page types:

components/layout/
├── DefaultLayout.tsx      # Standard pages
├── ArticleLayout.tsx      # Content-heavy pages
├── LandingLayout.tsx      # Marketing/hero pages
└── GridLayout.tsx         # Grid-based layouts

DefaultLayout

Used for: Most pages (contact, programs, etc.)

import Header from './Header'
import Footer from './Footer'

interface DefaultLayoutProps {
  children: React.ReactNode
}

export default function DefaultLayout({ children }: DefaultLayoutProps) {
  return (
    <div className="min-h-screen flex flex-col">
      <Header />
      <main className="flex-1">
        {children}
      </main>
      <Footer />
    </div>
  )
}

Features:

  • Header at top
  • Content in middle (flex-1 makes it grow)
  • Footer at bottom
  • Full height (min-h-screen)

Usage:

import DefaultLayout from '@/components/layout/DefaultLayout'

export default function ContactPage() {
  return (
    <DefaultLayout>
      <h1>Contact Us</h1>
      <ContactForm />
    </DefaultLayout>
  )
}

ArticleLayout

Used for: Content pages (about, model, etc.)

interface ArticleLayoutProps {
  title: string
  description?: string
  children: React.ReactNode
}

export default function ArticleLayout({ 
  title, 
  description, 
  children 
}: ArticleLayoutProps) {
  return (
    <div className="min-h-screen flex flex-col">
      <Header />
      <main className="flex-1">
        <div className="max-w-4xl mx-auto px-4 py-12">
          <h1 className="text-4xl font-bold">{title}</h1>
          {description && (
            <p className="text-xl text-gray-600 mt-4">{description}</p>
          )}
          <div className="mt-8 prose">
            {children}
          </div>
        </div>
      </main>
      <Footer />
    </div>
  )
}

Features:

  • Takes title as prop
  • Optional description
  • Centered content (max-w-4xl)
  • Typography styles (prose)

Usage:

import ArticleLayout from '@/components/layout/ArticleLayout'

export default function AboutPage() {
  return (
    <ArticleLayout 
      title="About K12worX"
      description="Our mission and approach"
    >
      <p>Content goes here...</p>
    </ArticleLayout>
  )
}

LandingLayout

Used for: Homepage and landing pages

export default function LandingLayout({ children }: { children: React.ReactNode }) {
  return (
    <div className="min-h-screen">
      <Header transparent />
      {children}
      <Footer />
    </div>
  )
}

Features:

  • Transparent header (overlays content)
  • No padding constraints
  • Full creative freedom for hero sections

Usage:

import LandingLayout from '@/components/layout/LandingLayout'

export default function Home() {
  return (
    <LandingLayout>
      <div className="hero bg-gradient-to-r from-blue-500 to-purple-600">
        <h1>Big Hero Title</h1>
      </div>
      {/* More sections */}
    </LandingLayout>
  )
}

Root Layout (Special)

File: app/layout.tsx

This is the top-level layout that wraps the entire app:

import './globals.css'
import AccessGate from '@/components/AccessGate'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <AccessGate enabled={true} passcode="2025">
          {children}
        </AccessGate>
      </body>
    </html>
  )
}

What it does:

  • Wraps EVERYTHING
  • Includes <html> and <body> tags
  • Loads global CSS
  • Applies access gate
  • Every page goes through this!

You rarely edit this - it's configured once and left alone.

Layout Hierarchy

Layouts can nest:

RootLayout (app/layout.tsx)
  └─ DefaultLayout (page's layout choice)
      └─ Page content

Example:

// Root layout wraps everything
<html>
  <body>
    <AccessGate>
      {/* DefaultLayout wraps this page */}
      <div>
        <Header />
        <main>
          {/* Your page content */}
          <h1>Contact Us</h1>
        </main>
        <Footer />
      </div>
    </AccessGate>
  </body>
</html>

When to Use Each Layout

LayoutWhen to UseExamples
DefaultLayoutStandard pagesContact, Programs
ArticleLayoutContent-heavy pagesAbout, Model
LandingLayoutMarketing pagesHomepage
GridLayoutGrid-based contentPhoto galleries

Creating a Custom Layout

Need a special layout? Follow this pattern:

// components/layout/CustomLayout.tsx

import Header from './Header'
import Footer from './Footer'

interface CustomLayoutProps {
  sidebar?: React.ReactNode
  children: React.ReactNode
}

export default function CustomLayout({ 
  sidebar, 
  children 
}: CustomLayoutProps) {
  return (
    <div className="min-h-screen flex flex-col">
      <Header />
      <div className="flex-1 flex">
        {sidebar && (
          <aside className="w-64 bg-gray-100">
            {sidebar}
          </aside>
        )}
        <main className="flex-1">
          {children}
        </main>
      </div>
      <Footer />
    </div>
  )
}

Usage:

<CustomLayout sidebar={<MySidebar />}>
  <h1>Page with sidebar</h1>
</CustomLayout>

Best Practices

1. Consistent Headers/Footers

Use the same Header and Footer components in all layouts:

// ✅ Good
<div>
  <Header />
  <main>{children}</main>
  <Footer />
</div>

// ❌ Bad: Different header each time
<div>
  <CustomHeader />
  <main>{children}</main>
  <DifferentFooter />
</div>

2. Props for Customization

Let pages customize the layout:

interface LayoutProps {
  children: React.ReactNode
  showSidebar?: boolean
  headerTransparent?: boolean
}

export default function Layout({ 
  children, 
  showSidebar = false,
  headerTransparent = false 
}: LayoutProps) {
  return (
    <div>
      <Header transparent={headerTransparent} />
      <div className="flex">
        {showSidebar && <Sidebar />}
        <main>{children}</main>
      </div>
    </div>
  )
}

3. Keep Layouts Simple

Layouts should be wrappers, not complex pages:

// ✅ Good: Simple wrapper
function Layout({ children }) {
  return (
    <>
      <Header />
      <main>{children}</main>
      <Footer />
    </>
  )
}

// ❌ Bad: Too much logic
function Layout({ children }) {
  const data = await fetchData()
  const processed = processData(data)
  // 100 more lines...
  return <div>...</div>
}

Common Patterns

Full-Height Layout

<div className="min-h-screen flex flex-col">
  <Header />
  <main className="flex-1">{children}</main>
  <Footer />
</div>

Result: Footer always at bottom, even on short pages!

Centered Content

<main>
  <div className="max-w-4xl mx-auto px-4">
    {children}
  </div>
</main>

Result: Content centered with max width.

<div className="flex">
  <aside className="w-64">{sidebar}</aside>
  <main className="flex-1">{children}</main>
</div>

Result: Fixed sidebar, flexible main content.

Quick Reference

Using a layout:

import DefaultLayout from '@/components/layout/DefaultLayout'

export default function MyPage() {
  return (
    <DefaultLayout>
      {/* Your content */}
    </DefaultLayout>
  )
}

Layout with props:

<ArticleLayout title="My Page" description="Description">
  {/* Content */}
</ArticleLayout>

Our layouts:

  • DefaultLayout - Standard pages
  • ArticleLayout - Content pages
  • LandingLayout - Hero/marketing
  • GridLayout - Grid content

Summary

Layouts:

  • Wrap pages with shared UI
  • Provide consistency across the site
  • Reduce code duplication
  • Accept children prop for page content

Our system:

  • Multiple layouts for different page types
  • All layouts include Header and Footer
  • Pages choose which layout to use

Best practice:

  • Use existing layouts when possible
  • Create custom layouts for special needs
  • Keep layouts simple and focused

Section Complete!

You now understand:

  • ✅ How the App Router works
  • ✅ How pages create routes
  • ✅ What components are and how to use them
  • ✅ How layouts provide consistent structure

Next Up

Let's read actual code from the codebase:

Continue to Section 04: Reading Code →