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:
- The
<Site>component providesHeaderandFooterautomatically - Your pages render in the
<main>area - Theme context wraps everything
- 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>Related Components
- Header Component - Navigation header
- Footer Component - Site footer
- LandingPage Component - Homepage layout
- Page Component - Generic page layout
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 />,
})