Custom Layout

Override the default docs layout with your own React component using docs/layout.tsx.

Boltdocs wraps every MDX page in a layout. By default, it uses DocsLayout which includes the navbar, sidebar, content area, and "On this page" navigation. You can override this by creating a custom layout.

Full Custom LayoutLink

For total control, build your own layout from primitives:

docs/layout.tsx
import { Navbar, Sidebar, OnThisPage, Breadcrumbs, PageNav } from 'boltdocs/client'

export default function CustomLayout({
  children,
  frontmatter,
  headings,
}: {
  children: React.ReactNode
  frontmatter: Record<string, any>
  headings: { id: string; text: string; level: number }[]
}) {
  return (
    <div className="min-h-screen">
      <Navbar />
      <div className="flex">
        <Sidebar />
        <div className="flex-1 max-w-4xl mx-auto px-8 py-12">
          <Breadcrumbs />
          <article className="prose dark:prose-invert max-w-none">
            {children}
          </article>
          <OnThisPage headings={headings} />
          <PageNav />
        </div>
      </div>
    </div>
  )
}

Layout PropsLink

Your custom layout receives these props:

PropTypeDescription
childrenReactNodeThe rendered MDX content
frontmatterRecord<string, any>The current page's frontmatter fields
headingsHeading[]Extracted headings for "On this page"

Heading TypeLink

ts
interface Heading {
  id: string
  text: string
  level: number // 1-6 (h1-h6)
}

Using DocsLayout ComponentsLink

Boltdocs exports layout primitives you can combine:

ComponentPurpose
DocsLayoutDefault layout with navbar, sidebar, content, "On this page"
NavbarTop navigation bar with tabs and search
SidebarLeft sidebar with collapsible groups and sections
OnThisPageRight-hand table of contents
BreadcrumbsRoute navigation below the navbar
PageNavPrevious/next page navigation at the bottom
SearchDialogGlobal search modal

Layout Example: Landing Page StyleLink

tsx
import { Navbar, SearchDialog } from 'boltdocs/client'

export default function LandingLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div className="min-h-screen bg-linear-to-b from-white to-zinc-50 dark:from-zinc-900 dark:to-zinc-950">
      <Navbar />
      <SearchDialog />
      <main className="max-w-5xl mx-auto px-6 py-20">
        {children}
      </main>
    </div>
  )
}

Conditional LayoutsLink

Use frontmatter to select different layouts:

tsx
// docs/layout.tsx
import { DocsLayout } from 'boltdocs/client'

export default function Layout(props: any) {
  if (props.frontmatter?.layout === 'landing') {
    return <LandingLayout {...props} />
  }
  return <DocsLayout>{props.children}</DocsLayout>
}

Then in your MDX:

md
---
title: Welcome
layout: landing
---

Combining with External PagesLink

External pages (pages-external/) have their own layout export. Use the same approach for consistency:

tsx
// docs/pages-external/index.tsx
import { Navbar } from 'boltdocs/client'
import CustomPage from './CustomPage'

export const pages = {
  '/custom': CustomPage,
}

export const layout = ({ children }: { children: React.ReactNode }) => (
  <div className="custom-wrapper">
    <Navbar />
    {children}
  </div>
)

Performance NotesLink

  • Custom layouts are server-rendered during SSG
  • In dev mode, layout changes trigger hot reload
  • Heavy custom layouts can slow down initial load — keep them lightweight
Last updated on October 18, 2026

Was this page helpful?