A layout is a TSX file in src/layouts that renders the full document — <html>, <head>, and <body>. A page selects it with the layout frontmatter field: layout: "doc" renders with src/layouts/doc.tsx.
Props
A layout receives one props object: the page frontmatter plus Sitex-provided path, url, locale, headings, and children. Type extra frontmatter with LayoutProps<T>:
import type { LayoutProps } from "@fulldotdev/sitex"
type PostData = { badge?: string }
export default function PostLayout({
title,
badge,
headings,
children,
}: LayoutProps<PostData>) {
return (
<html>
<head>
<title>{title}</title>
</head>
<body>
<nav>
{headings.map((h) => (
<a key={h.id} href={h.href}>
{h.label}
</a>
))}
</nav>
<article>
<h1>{title}</h1>
{badge && <span>{badge}</span>}
{children}
</article>
</body>
</html>
)
}Sitex writes one typecheck file per page to .sitex/typecheck, so tsc reports frontmatter that does not match the layout props.
Globals
Shared chrome content — name, logo, navigation, footer links — lives in src/globals/index.yaml and is imported with sitex:globals (fully typed from the YAML):
import globals from "sitex:globals"index.yaml serves the root locale; its language tag comes from the site.locale plugin option (default "en") and sets <html lang>. Files like nl.yaml define locale variants served under /nl routes, available via the locales export and the layout locale prop.
Head Defaults
The layout owns the <head>. After rendering, Sitex adds only what is missing:
- canonical link and
og:urlfrom the site URL + the page path (canonicalfrontmatter overrides) <html lang>from the page locale- charset and viewport
- robots
noindexwhen the page setsnoindex: true - favicon link and generator meta
For JSON-LD, render a script type="application/ld+json" anywhere in the layout — Sitex hoists it into the head. The layout component from pre-built components wires title, description, Open Graph, Twitter, and JSON-LD props for you.
MDX Components
Override Markdown elements globally in the plugin config, or per layout with an mdxComponents export. Layout entries win. Use this for elements that need more than CSS — the main case is code blocks with syntax highlighting and a copy button, which the registry ships as the code component:
pnpm dlx shadcn@latest add https://sitex.full.dev/r/code.json// vite.config.ts
sitex({ mdx: { components: { pre: "@/components/ui/code" } } })// src/layouts/doc.tsx — per-layout override, wins over the config
import CodePre from "@/components/ui/code"
export const mdxComponents = { pre: CodePre }