mdxui

Site Component

The root wrapper component that provides global layout and context

Site Component

The <Site> component is the root container for all marketing sites, landing pages, blogs, and documentation. It provides the layout shell (Header + Footer), theme context, and global metadata.

Interface

import type { SiteProps } from 'mdxui'

interface SiteProps {
  /** Site display name */
  name: string
  /** Primary domain (e.g., "example.com") */
  domain?: string
  /** Theme mode */
  theme?: 'light' | 'dark' | 'system'
  /** Child content (pages) */
  children: ReactNode
}

Usage

Basic Example

import { Site, Header, Footer, LandingPage } from '@mdxui/beacon'

<Site name="Acme Inc" theme="system">
  <LandingPage>
    <Hero title="Welcome to Acme" />
    <Features />
    <Pricing />
  </LandingPage>
</Site>

The <Site> component automatically wraps your content with:

  • <Header> navigation
  • Main content area
  • <Footer> links and legal

With Domain

<Site
  name="Acme Inc"
  domain="acme.com"
  theme="dark"
>
  {/* Pages... */}
</Site>

Props

name (required)

Type: string

The display name of your site. Used in:

  • Page titles
  • Metadata
  • Copyright text
<Site name="Acme Inc">

domain (optional)

Type: string

Primary domain for the site. Used for:

  • Canonical URLs
  • Social meta tags
  • Sitemap generation
<Site domain="acme.com">

theme (optional)

Type: 'light' | 'dark' | 'system' Default: 'system'

Theme mode preference:

  • 'light' - Always light mode
  • 'dark' - Always dark mode
  • 'system' - Follow system preference
<Site theme="dark">

children (required)

Type: ReactNode

Page components and content. Typically contains:

  • <LandingPage> - Homepage
  • <Page> - Content pages
  • <Blog> - Blog listing
  • <Docs> - Documentation
<Site name="Acme">
  <LandingPage>...</LandingPage>
  <Page path="/about">...</Page>
  <Blog />
  <Docs />
</Site>

Layout Structure

The <Site> component renders with this structure:

<div className="site-wrapper">
  <Header {...headerProps} />
  <main>
    {children}
  </main>
  <Footer {...footerProps} />
</div>

How it works:

  1. The <Site> component provides Header and Footer automatically
  2. Your pages render in the <main> area
  3. Theme context wraps everything
  4. Navigation and footer links are configured per implementation

Implementation Pattern

The <Site> component is part of the SiteComponents interface. Here's how it's typically implemented:

// Template implementation
import type { SiteComponents } from 'mdxui'
import { ThemeProvider } from '@mdxui/primitives'

export const Site: Component<SiteProps> = ({
  name,
  domain,
  theme = 'system',
  children
}) => {
  return (
    <ThemeProvider defaultTheme={theme}>
      <div className="site-wrapper">
        <Header
          logo={<Logo>{name}</Logo>}
          // ... navigation config
        />
        <main>{children}</main>
        <Footer
          logo={<Logo>{name}</Logo>}
          companyName={name}
          // ... footer config
        />
      </div>
    </ThemeProvider>
  )
}

Site Types

Different site types determine default pages and structure:

Marketing Site

Focused on conversion with hero, features, pricing.

<Site name="Acme" type="marketing">
  <LandingPage>
    <Hero />
    <Features />
    <Pricing />
    <Testimonials />
    <CTA />
  </LandingPage>
  <Page path="/about">...</Page>
  <Page path="/contact">...</Page>
  <Blog />
</Site>

Documentation Site

Developer-focused with docs, API reference, examples.

<Site name="Acme Docs" type="docs">
  <DocsPage>
    <GettingStarted />
    <APIReference />
    <Examples />
  </DocsPage>
</Site>

Blog Site

Content-first with posts, authors, categories.

<Site name="Acme Blog" type="blog">
  <BlogPage />
  <BlogPost />
  <AuthorPage />
  <CategoryPage />
</Site>

API Site

API-first with docs, playground, SDKs.

<Site name="Acme API" type="api">
  <APILandingPage />
  <DocsPage />
  <PlaygroundPage />
  <SDKsPage />
  <StatusPage />
</Site>

See Site Types for the complete taxonomy.


Payload Integration

When using Payload CMS, the <Site> component auto-wires to the sites collection:

Collection Schema:

{
  slug: 'sites',
  fields: [
    { name: 'name', type: 'text', required: true },
    { name: 'domain', type: 'text' },
    { name: 'theme', type: 'select', options: ['light', 'dark', 'system'] },
    { name: 'type', type: 'select', options: ['marketing', 'docs', 'blog', 'api'] },
  ]
}

Auto-fetch:

// Automatically fetches site config from Payload
<Site /> // Uses current site context

// Or specify explicitly
<Site id="acme-site" />

Composition with SiteComponents

The <Site> component is part of the SiteComponents interface:

import type { SiteComponents } from 'mdxui'

export const components: SiteComponents = {
  // Required layout
  Site,           // This component
  Header,         // Navigation
  Footer,         // Footer links
  LandingPage,    // Homepage
  Page,           // Content pages

  // Optional sections
  Hero,
  Features,
  Pricing,

  // Optional content
  Blog,
  Docs,
}

Usage in MDX:

export { components } from './components'

<Site name="Acme">
  <LandingPage>
    <Hero title="Welcome" />
  </LandingPage>
</Site>

Best Practices

Keep Site Config Simple

The <Site> component should focus on global concerns:

// Good - global config
<Site name="Acme" theme="system">

// Avoid - page-specific config (use Page props instead)
<Site name="Acme" heroTitle="Welcome"> // ❌

Use Site Context

Many templates provide a useSite() hook to access site config:

import { useSite } from '@mdxui/beacon'

function MyComponent() {
  const { name, domain, theme } = useSite()
  return <div>Welcome to {name}</div>
}

Separate Header/Footer Config

Configure Header and Footer props separately from Site:

<Site name="Acme">
  <Header
    logo={<Logo />}
    links={navLinks}
    primaryCta="Sign Up"
  />
  {/* Pages */}
  <Footer
    linkGroups={footerLinks}
    socialLinks={social}
  />
</Site>


TypeScript

Full type definitions:

import type { ReactNode } from 'react'
import type { z } from 'zod'

export const SitePropsSchema = z.object({
  name: z.string(),
  domain: z.string().optional(),
  theme: z.enum(['light', 'dark', 'system']).default('system'),
  children: z.any(),
})

export type SiteProps = z.infer<typeof SitePropsSchema>

export type Site = Component<SiteProps>

Zod Validation:

import { SitePropsSchema } from 'mdxui/zod'

// Validate props at runtime
const props = SitePropsSchema.parse({
  name: "Acme",
  theme: "dark",
  children: <LandingPage />,
})

On this page