Skip to main content

cn

Utility function for merging Tailwind CSS classes.
import { cn } from 'fumadocs-ui/utils/cn';

Signature

function cn(...inputs: ClassValue[]): string
This is a re-export of twMerge from tailwind-merge for convenient class name merging.

Usage

import { cn } from 'fumadocs-ui/utils/cn';

function Button({ className, variant }) {
  return (
    <button
      className={cn(
        'px-4 py-2 rounded',
        variant === 'primary' && 'bg-blue-500 text-white',
        variant === 'secondary' && 'bg-gray-200 text-black',
        className
      )}
    >
      Click me
    </button>
  );
}

useCopyButton

Hook for implementing copy-to-clipboard functionality with visual feedback.
import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';

Signature

function useCopyButton(
  onCopy: () => void | Promise<void>
): [checked: boolean, onClick: MouseEventHandler]

Parameters

onCopy
() => void | Promise<void>
required
Function to execute when copy is triggered (typically writing to clipboard)

Returns

Returns a tuple:
  • checked (boolean) - True for 1.5s after successful copy
  • onClick (MouseEventHandler) - Click handler for copy button

Usage

import { useCopyButton } from 'fumadocs-ui/utils/use-copy-button';
import { Check, Copy } from 'lucide-react';

function CopyCodeButton({ code }: { code: string }) {
  const [copied, onClick] = useCopyButton(() => {
    return navigator.clipboard.writeText(code);
  });
  
  return (
    <button onClick={onClick}>
      {copied ? <Check /> : <Copy />}
      {copied ? 'Copied!' : 'Copy'}
    </button>
  );
}

mergeRefs

Merge multiple React refs into a single callback ref.
import { mergeRefs } from 'fumadocs-ui/utils/merge-refs';

Signature

function mergeRefs<T>(
  ...refs: (React.Ref<T> | undefined)[]
): React.RefCallback<T>

Usage

import { mergeRefs } from 'fumadocs-ui/utils/merge-refs';
import { useRef, forwardRef } from 'react';

const Component = forwardRef<HTMLDivElement>((props, forwardedRef) => {
  const localRef = useRef<HTMLDivElement>(null);
  
  return (
    <div 
      ref={mergeRefs(localRef, forwardedRef)}
      {...props}
    />
  );
});

isActive

Check if a URL/path is active based on current pathname.
import { isActive } from 'fumadocs-ui/utils/urls';

Signature

function isActive(
  href: string,
  pathname: string,
  nested?: boolean
): boolean

Parameters

href
string
required
Link URL to check
pathname
string
required
Current pathname
nested
boolean
If true, also matches nested paths (default: false)

Usage

import { isActive } from 'fumadocs-ui/utils/urls';
import { usePathname } from 'next/navigation';

function NavLink({ href, children }) {
  const pathname = usePathname();
  const active = isActive(href, pathname, true);
  
  return (
    <a 
      href={href}
      className={active ? 'font-bold' : ''}
    >
      {children}
    </a>
  );
}

normalize

Normalize URLs by removing trailing slashes.
import { normalize } from 'fumadocs-ui/utils/urls';

Signature

function normalize(urlOrPath: string): string

Usage

import { normalize } from 'fumadocs-ui/utils/urls';

normalize('/docs/');     // '/docs'
normalize('/docs');      // '/docs'
normalize('/');          // '/'

useFooterItems

Get a flattened list of all page items in the current tree for footer navigation.
import { useFooterItems } from 'fumadocs-ui/utils/use-footer-items';

Signature

function useFooterItems(): PageTree.Item[]

Returns

Array of page tree items (pages only, excluding folders and external links)

Usage

import { useFooterItems } from 'fumadocs-ui/utils/use-footer-items';
import { usePathname } from 'next/navigation';

function PageNavigation() {
  const items = useFooterItems();
  const pathname = usePathname();
  
  const currentIndex = items.findIndex(item => item.url === pathname);
  const previous = items[currentIndex - 1];
  const next = items[currentIndex + 1];
  
  return (
    <nav>
      {previous && (
        <a href={previous.url}>{previous.name}</a>
      )}
      {next && (
        <a href={next.url}>{next.name}</a>
      )}
    </nav>
  );
}

LinkItem

Component for rendering navigation links with active state.
import { LinkItem } from 'fumadocs-ui/utils/link-item';

Props

Extends ComponentProps<'a'> (excluding href)
item
LinkItemType
required
Link configuration object

LinkItemType

Union type supporting multiple link types:

MainItemType

type
'main'
Main navigation link
text
ReactNode
required
Link text
url
string
required
Link URL
icon
ReactNode
Link icon
description
ReactNode
Link description
active
'url' | 'nested-url' | 'none'
Active state matching (default: 'url')
external
boolean
External link
on
'menu' | 'nav' | 'all'
Where to display link (default: 'all')

IconItemType

type
'icon'
required
Icon-only link
icon
ReactNode
required
Icon element
label
string
Aria-label for accessibility

ButtonItemType

type
'button'
required
Button-style link
secondary
boolean
Use secondary styling (default: false)
type
'menu'
required
Dropdown menu with sub-items
items
(MainItemType | CustomItemType)[]
required
Menu items

CustomItemType

type
'custom'
required
Custom content
children
ReactNode
required
Custom content to render

Usage

import { LinkItem } from 'fumadocs-ui/utils/link-item';
import { GithubIcon } from 'lucide-react';

const links = [
  {
    type: 'main' as const,
    url: '/docs',
    text: 'Documentation',
    icon: <BookIcon />
  },
  {
    type: 'icon' as const,
    url: 'https://github.com/user/repo',
    text: 'GitHub',
    icon: <GithubIcon />,
    label: 'GitHub Repository',
    external: true
  }
];

function Navigation() {
  return (
    <nav>
      {links.map((item, i) => (
        <LinkItem key={i} item={item} />
      ))}
    </nav>
  );
}

useLinkItemActive

Determine if a link item is active.
import { useLinkItemActive } from 'fumadocs-ui/utils/link-item';

Signature

function useLinkItemActive(link: LinkItemType): boolean

Usage

import { useLinkItemActive } from 'fumadocs-ui/utils/link-item';

function CustomNavLink({ item }) {
  const active = useLinkItemActive(item);
  
  return (
    <a 
      href={item.url}
      data-active={active}
      className="data-[active=true]:font-bold"
    >
      {item.text}
    </a>
  );
}

resolveLinkItems

Resolve link items with shortcuts (e.g., auto-adding GitHub icon).
import { resolveLinkItems } from 'fumadocs-ui/layouts/shared';

Signature

function resolveLinkItems({
  links,
  githubUrl
}: {
  links?: LinkItemType[];
  githubUrl?: string;
}): LinkItemType[]

Usage

import { resolveLinkItems } from 'fumadocs-ui/layouts/shared';

const links = resolveLinkItems({
  links: [
    { type: 'main', url: '/docs', text: 'Docs' }
  ],
  githubUrl: 'https://github.com/user/repo'
});
// Returns: [...original links, GitHub icon link]

useLinkItems

Hook to categorize links for different layout areas.
import { useLinkItems } from 'fumadocs-ui/layouts/shared';

Signature

function useLinkItems({
  links,
  githubUrl
}: {
  links?: LinkItemType[];
  githubUrl?: string;
}): {
  navItems: LinkItemType[];
  menuItems: LinkItemType[];
  all: LinkItemType[];
}

Returns

navItems
LinkItemType[]
Links for navbar (items with on: 'nav' or on: 'all')
menuItems
LinkItemType[]
Links for sidebar/menu (items with on: 'menu' or on: 'all')
all
LinkItemType[]
All resolved links

Usage

import { useLinkItems } from 'fumadocs-ui/layouts/shared';

function Layout({ links, githubUrl }) {
  const { navItems, menuItems } = useLinkItems({ links, githubUrl });
  
  return (
    <>
      <nav>
        {navItems.map((item, i) => (
          <NavItem key={i} item={item} />
        ))}
      </nav>
      <aside>
        {menuItems.map((item, i) => (
          <MenuItem key={i} item={item} />
        ))}
      </aside>
    </>
  );
}

Build docs developers (and LLMs) love