1. Home
  2. ChevronRightLayout
  3. ChevronRightDocsLayout

DocsLayout

The page shell — composes navbar, sidebar, content, and ToC into a single React tree.

DocsLayoutLink

DocsLayout is the outermost wrapper around any docs page. It doesn't do much visually — instead, it splits the screen into named, themed slots that the rest of the UI hooks into. Most custom layouts only need to swap two or three of its sub-components.

The default implementation in Boltdocs already wires Navbar, Sidebar, OnThisPage, breadcrumbs, and so on. You don't need to use it. But if you're building a custom theme, copying the assembly pattern is the fastest way to get consistent spacing, scrolling, and z-index behavior for free.


ImportLink

import { DocsLayout } from 'boltdocs/primitives'

The mental modelLink

Every Boltdocs page has seven regions that plugin authors and custom layouts may want to write into:

┌─ Navbar ──────────────────────────────────────────┐  ← sticky top
├─ Body ─────────────────────────────────────────────┤
│  ┌─ Sidebar ─┐  ┌─ Content ────────┐  ┌─ ToC ────┐ │
│  │           │  │  ┌─ Header ──┐  │  │           │ │
│  │           │  │  │  crumbs   │  │  │           │ │
│  │           │  │  │  title    │  │  │           │ │
│  │           │  │  └───────────┘  │  │           │ │
│  │           │  │  ┌─ MDX ───────┐  │  │           │ │
│  │           │  │  │  ...children │  │  │           │ │
│  │           │  │  └─────────────┘  │  │           │ │
│  │           │  │  ┌─ Footer ───┐  │  │           │ │
│  │           │  │  │  PageNav   │  │  │           │ │
│  │           │  │  └────────────┘  │  │           │ │
│  └───────────┘  └──────────────────┘  └───────────┘ │
└───────────────────────────────────────────────────┘
        Floating elements outside this tree:
        • FloatingBottom — bubble pinned to viewport corner
        • RightRail      — vertical column on lg+ viewports
        • BodyPortal     — `createPortal` to `document.body`

DocsLayout exposes one named sub-component per region. Inside your custom layout, you decide which ones get a Navbar, which one gets a Sidebar, etc.


Sub-componentsLink

Sub-componentRendersPurpose
DocsLayout (root)<div>The outer flex column container. Sets app-wide background, scrolling, and color defaults.
DocsLayout.Body<div>The horizontal row that holds Sidebar + Content + ToC.
DocsLayout.Content<main>The scrollable middle column. The actual page goes here.
DocsLayout.ContentMdx<div>An inner padded wrapper that constrains content to a max-width reading column.
DocsLayout.Header<header>Above-body section. Best home for breadcrumbs + page title + description.
DocsLayout.Footer<div>Below-body section. Best home for PageNav.
DocsLayout.FloatingBottom<div> (fixed)Pinned to bottom-6 right-6. Hosts floating widgets like "Ask AI" buttons.
DocsLayout.RightRail<aside> (fixed)Vertical column on the right edge on xl+ viewports. Persistence + scrollable.
DocsLayout.BodyPortal<div>Anything you wrap here is portalled into document.body. Modals, toasts, global overlays.

Every sub-component accepts children, className, and style. There are no surprise props — they're extensions of a minimal HTML pass-through.


Minimal layoutLink

The smallest layout that makes sense: a navbar at the top and the page content in the middle. The Sidebar and OnThisPage are optional.

// my-docs/layout.tsx
import { DocsLayout, Navbar } from 'boltdocs/primitives'

export default function MyLayout({ children }: { children: React.ReactNode }) {
  return (
    <DocsLayout>
      <Navbar>...</Navbar>
      <DocsLayout.Body>
        <DocsLayout.Content>
          <DocsLayout.ContentMdx>{children}</DocsLayout.ContentMdx>
        </DocsLayout.Content>
      </DocsLayout.Body>
    </DocsLayout>
  )
}

That's the entire page. Add Sidebar to the left, OnThisPage to the right, and you have a fully built docs site.


Real-world layout, with everythingLink

The layout we ship as a default. It uses every named slot. Use it as a copy-paste starting point when you want to make a custom theme that still feels "stock Boltdocs":

// src/components/ProductionDocsLayout.tsx
import {
  DocsLayout,
  Navbar,
  Sidebar,
  OnThisPage,
  Breadcrumbs,
  PageNav,
  ErrorBoundary,
} from 'boltdocs/primitives'
import { useRoutes } from 'boltdocs/client'
import { ProductionNavbar } from './ProductionNavbar'
import { ProductionSidebar } from './ProductionSidebar'

export function ProductionDocsLayout({ children }: { children: React.ReactNode }) {
  const { currentRoute } = useRoutes()

  return (
    // 1. Outer shell — sets background + scroll behavior
    <DocsLayout className="min-h-screen selection:bg-primary-500/10 selection:text-primary-500">
      {/* The navbar lives outside DocsLayout.Body so it spans full width. */}
      <ProductionNavbar />

      {/* 2. Body row: sidebar + content + ToC */}
      <DocsLayout.Body className="bg-main">
        <ProductionSidebar />

        <DocsLayout.Content className="scroll-smooth">
          <DocsLayout.ContentMdx className="max-w-3xl px-4 pt-8 pb-24 mx-auto">

            {/* 3. Page header — breadcrumbs + title + description */}
            <DocsLayout.Header>
              <Breadcrumbs />

              {currentRoute?.title && (
                <h1 className="text-4xl font-bold tracking-tight mt-4">
                  {currentRoute.title}
                </h1>
              )}
              {currentRoute?.description && (
                <p className="text-lg text-muted leading-relaxed mt-3">
                  {currentRoute.description}
                </p>
              )}
            </DocsLayout.Header>

            {/* 4. Article body — wrapped in an Error Boundary */}
            <ErrorBoundary>
              <article className="prose dark:prose-invert max-w-none">
                {children}
              </article>
            </ErrorBoundary>

            {/* 5. Footer — previous/next links */}
            <DocsLayout.Footer className="mt-12">
              <PageNav />
            </DocsLayout.Footer>

          </DocsLayout.ContentMdx>
        </DocsLayout.Content>

        {/* 6. Right rail — table of contents (sticky, scroll-spy) */}
        <OnThisPage.Tree headings={currentRoute?.headings} />
      </DocsLayout.Body>

      {/* 7. Floating widgets — outside the body flex */}
      <DocsLayout.FloatingBottom>
        <AskAiBubble /> {/* e.g. from `@bdocs/plugin-ask-ai` */}
      </DocsLayout.FloatingBottom>

      <DocsLayout.RightRail>
        <RightRailAskAiHistory />
      </DocsLayout.RightRail>

      {/* 8. Body portal — modal mounts, toast roots, etc. */}
      <DocsLayout.BodyPortal>
        <ToastContainer />
      </DocsLayout.BodyPortal>
    </DocsLayout>
  )
}

A few details worth calling out:

  • Navbar is outside DocsLayout.Body. That keeps the navbar full-width while everything else shares the constrained body row.
  • FloatingBottom / RightRail / BodyPortal are outside the body flex. They're positioned with fixed so they can escape the layout flow.
  • ErrorBoundary sits around the article body only. Crashes there won't hide the navbar, breadcrumbs, or footer.

Floating widgets & portalsLink

The three "floating" sub-components behave differently from the others:

  • DocsLayout.FloatingBottom is a position: fixed container pinned bottom-right. Use it for chat bubbles, "back to top" buttons, or any small persistent widget.
  • DocsLayout.RightRail is a position: fixed vertical column on the right edge. Use it for chat histories, conversation sidebars, or persistent drawers that shouldn't be inside the article.
  • DocsLayout.BodyPortal uses createPortal to render its children into document.body. Use it when you need a modal/toast to escape overflow: hidden containers.

You don't have to mount them — they're all optional. Mount only what you use.


Common decisionsLink

  • Need a sticky ToC? Put <OnThisPage.Tree> inside DocsLayout.Body on the right. Boltdocs already ships one; copy it for your theme.
  • Making the content narrower on mobile? ContentMdx accepts max-w-{value} via className. The default is unset — pass your own width.
  • Debugging a layout issue? Set a red border on each sub-component (border border-red-500) and walk down the tree.

Where nextLink

Last updated on July 27, 2026

Was this page helpful?