Layouts
Customize the navbar, the docs page and custom pages.
Overview
The integration renders pages with Fumadocs UI layouts. You customize them with React modules that run in the browser as islands:
| Module | Exports |
|---|---|
layout | baseOptions(), layout options, and Provider. |
page | The docs page component, as default export. |
Layout Options
Create a module exporting baseOptions(), which returns the layout options, JSX included:
import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
import { appName, gitConfig } from './shared';
export function baseOptions(): BaseLayoutProps {
return {
nav: {
// JSX supported
title: appName,
},
githubUrl: `https://github.com/${gitConfig.user}/${gitConfig.repo}`,
};
}
The options apply to every layout: docs pages, custom pages and the 404 page.
Without it, the navbar shows your Fumadocs config's title.
Provider
The integration renders the root provider for you. To render components inside it like WebMCP, export Provider from the layout module:
import type { ReactNode } from 'react';
import { WebMCP } from '@/components/webmcp';
export function Provider({ children }: { children: ReactNode }) {
return (
<>
<WebMCP />
{children}
</>
);
}It wraps every layout, but not the content components -- those render in their own islands.
Docs Page
The docs page is a React component, like page.tsx on other frameworks. Create a module whose default export renders it:
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import {
DocsDescription,
DocsPage,
DocsTitle,
MarkdownCopyButton,
PageLastUpdate,
ViewOptionsPopover,
} from 'fumadocs-ui/layouts/docs/page';
import type { DocsPageProps } from '@fumadocs/astro/config';
/**
* The docs page, the content is passed as children.
*/
export default function Docs({ tree, page, layout, children }: DocsPageProps) {
return (
<DocsLayout {...layout} tree={tree}>
<DocsPage toc={page.toc} full={page.full}>
<DocsTitle>{page.title}</DocsTitle>
<DocsDescription>{page.description}</DocsDescription>
{page.markdownUrl && (
<div className="flex flex-row gap-2 items-center border-b -mt-4 pb-6">
<MarkdownCopyButton markdownUrl={page.markdownUrl} />
<ViewOptionsPopover markdownUrl={page.markdownUrl} githubUrl={page.githubUrl} />
</div>
)}
{children}
{page.lastModified && <PageLastUpdate date={page.lastModified} />}
</DocsPage>
</DocsLayout>
);
}
It receives:
tree: the page tree.layout: thebaseOptions()result.page: page data.children: the content.
Prop
Type
Use any Fumadocs UI layout or component here, such as the Notebook layout for some pages:
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { DocsLayout as NotebookLayout } from 'fumadocs-ui/layouts/notebook';
import type { DocsPageProps } from '@fumadocs/astro/config';
export default function Docs({ tree, page, layout, children }: DocsPageProps) {
// `type` is the key of its source in `loader()`
const Layout = page.type === 'api' ? NotebookLayout : DocsLayout;
// ...
}Custom Pages
Use HomeLayout.astro for custom pages, with the navbar from your layout options:
---
import HomeLayout from '@fumadocs/astro/components/HomeLayout.astro';
---
<HomeLayout>
<main class="flex flex-col flex-1 items-center justify-center gap-4 text-center">
<h1 class="text-xl font-bold">Fumadocs on Astro.</h1>
<a class="underline" href="/docs">Open Docs</a>
</main>
</HomeLayout>
Anything in its head slot goes into <head>. Props: title, description, lang (for internationalization) and notFound.
Your pages can read your docs from the source:
---
import HomeLayout from '@fumadocs/astro/components/HomeLayout.astro';
import { source } from '@/lib/source';
---
<HomeLayout title="All Pages">
<ul>
{source.getPages().map((page) => <li><a href={page.url}>{page.data.title}</a></li>)}
</ul>
</HomeLayout>A custom page takes priority over a docs page at the same URL. Remove the MDX file to avoid a warning from Astro. To replace the 404 page, create src/pages/404.astro.
React Content
Render React content with ReactContent.astro to hydrate it like docs content: it renders on the server and your MDX components hydrate, like code block copy buttons.
---
import { createElement } from 'react';
import HomeLayout from '@fumadocs/astro/components/HomeLayout.astro';
import ReactContent from '@fumadocs/astro/components/ReactContent.astro';
import { Timeline } from '@/components/timeline';
---
<HomeLayout title="Changelog">
<ReactContent node={createElement(Timeline)} />
</HomeLayout>Head
Add tags to the <head> of every page with an Astro component:
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
On docs pages, it receives page data as page.
Styles
The pages load src/styles/global.css, see Themes for its colors and presets. Set css for another file:
fumadocs({
css: './src/styles/docs.css',
});How is this guide?
Last updated on
