Orientation
Content Processing
Search Infrastructure
Rendering and UI
Developer Tooling
How It Works
The following files were used as context for generating this wiki page:
Base Components constitute the foundational UI building blocks in the Fumadocs architecture, designed to provide a consistent, reusable, and accessible interface for documentation sites. These components abstract low-level primitives into domain-specific modules like sidebars, code blocks, and interactive tabs, ensuring that functionality remains decoupled from specific layout implementations. By standardizing these components, the system facilitates rapid development of documentation layouts while maintaining a high degree of customizability.
At the core of these components is a focus on "mechanism over style." Many components rely on context providers (SidebarContext, TabsContext, FolderContext) to share state across deep component hierarchies, allowing for behaviors like automatic scrolling, shared keyboard navigation, and synced UI states. This architecture enables developers to compose complex documentation features (such as collapsible navigation trees) without manual state management.
The system is split into two primary implementation tiers: base-ui and radix-ui. While they share identical external APIs and shared logic, the radix-ui variant leverages Radix UI primitives, providing a different set of underlying behaviors and accessibility features compared to the standard base-ui implementation. This duality ensures that Fumadocs can support diverse technical requirements while maintaining a unified interface for the developer.
The sidebar system is a complex subsystem composed of providers and specialized slots. It manages navigation state, responsive behaviors (drawer vs. full-width), and folder expansion. The state is maintained in SidebarContext and FolderContext, allowing nested components like SidebarFolder, SidebarItem, and SidebarTrigger to react to global changes in the sidebar state.
The core mechanism for responsiveness relies on useMediaQuery to toggle between drawer and full modes. In drawer mode, the sidebar uses an overlay element managed by Presence to handle animations.
Sources: packages/radix-ui/src/components/sidebar/base.tsx:32-45, packages/radix-ui/src/components/sidebar/base.tsx:75-112
Tip
Use the defaultOpenLevel prop in SidebarProvider to control the initial expansion state of folders. Folders with a depth less than or equal to this level will automatically initialize as expanded.
The Tabs component implements a robust collection mechanism inspired by Headless UI to handle child order and selection. Instead of relying on manual index management, each Tab component uses a unique ID (useId) and registers itself into a shared collection array held in TabsContext.
When Tab renders, it calls useCollectionIndex() which performs the following logic:
Sources: packages/base-ui/src/components/tabs.tsx:184-197
The CodeBlock component handles code highlighting visualization with built-in actions like copying. It leverages useCopyButton to orchestrate clipboard interactions. A significant detail in the copying mechanism is the handling of non-copyable elements via cloneNode:
containerRef is used to retrieve the inner re> tag.cloneNode(true) creates a deep clone of the content to avoid modifying the visual DOM..nd-copy-ignore class before executing navigator.clipboard.writeText.const [checked, onClick] = useCopyButton(() => {
const pre = containerRef.current?.getElementsByTagName('pre').item(0);
if (!pre) return;
const clone = pre.cloneNode(true) as HTMLElement;
clone.querySelectorAll('.nd-copy-ignore').forEach((node) => {
node.replaceWith('\n');
});
void navigator.clipboard.writeText(clone.textContent ?? '');
});Sources: packages/base-ui/src/components/codeblock.tsx:157-167
The Accordion component integrates with the auto-anchor system to support deep-linking directly to specific accordion sections. This is implemented via a useEffect inside AccordionItem that monitors the URL hash and automatically opens the corresponding accordion section if it matches the generated id.
The anchorIdStartsWith guard is crucial here: it verifies if the hash segment matches the section's ID, preventing arbitrary hash triggers from opening unrelated accordions.
Sources: packages/api-docs/src/components/accordion.tsx:43-46
The sidebar uses a custom useAutoScroll hook to keep active items in view within the viewport. This is triggered whenever an item becomes active. The mechanism calculates the boundary of the sidebar based on its current mode:
nd-sidebar-mobile.nd-sidebar.The scrollIntoView library is invoked with { scrollMode: 'if-needed' } to ensure the sidebar does not jitter or force-scroll if the item is already visible.
Sources: packages/radix-ui/src/components/sidebar/base.tsx:402-410
Callouts support multiple types, but the implementation allows for aliasing to maintain backwards compatibility or semantic clarity. The resolveAlias function handles these mappings before the visual container is rendered:
The resolve logic ensures that the internal CSS variable --callout-color correctly maps to the corresponding theme variable (e.g., --color-fd-info or --color-fd-warning).
Sources: packages/base-ui/src/components/callout.tsx:34-38
Caution
Manually overriding style on a CalloutContainer may break the automatic --callout-color calculation. If custom styling is required, use the className prop to target the container directly rather than overriding the internal CSS variables.