XYLEX Group

Next.js

Setup Fumadocs on Next.js.

Prerequisite

Before continuing, make sure you have configured:

  • Next.js 15.
  • Tailwind CSS 4.

We will use Fumadocs MDX as a content source, you can configure it first:

Good to Know

Fumadocs also supports other content sources, including Content Collections and headless CMS.

Getting Started

npm i fumadocs-ui fumadocs-core

Root Layout

Wrap the entire application inside Root Provider, and add required styles to body.

import { RootProvider } from 'fumadocs-ui/provider/next';
import type { ReactNode } from 'react';

export default function Layout({ children }: { children: ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body
        // required styles [!code ++]
        className="flex flex-col min-h-screen"
      >
        <RootProvider>{children}</RootProvider>
      </body>
    </html>
  );
}

Styles

Add the following Tailwind CSS styles to global.css.

@import 'tailwindcss';
/* [!code ++:2] */
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';

It doesn't come with a default font, you may choose one from next/font.

Routes

Create a lib/layout.shared.tsx file to put the shared options for our layouts.

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

export function baseOptions(): BaseLayoutProps {
  return {
    nav: {
      title: 'XYLEX Group',
    },
  };
}

Create the following files & routes:

import defaultMdxComponents from 'fumadocs-ui/mdx';
import type { MDXComponents } from 'mdx/types';

export function getMDXComponents(components?: MDXComponents): MDXComponents {
  return {
    ...defaultMdxComponents,
    ...components,
  };
}
import { source } from '@/lib/source';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/lib/layout.shared';

export default function Layout({ children }: LayoutProps<'/docs'>) {
  return (
    <DocsLayout tree={source.pageTree} {...baseOptions()}>
      {children}
    </DocsLayout>
  );
}
import { getPageImage, source } from "@/lib/source";
import {
  DocsBody,
  DocsDescription,
  DocsPage,
  DocsTitle,
} from "fumadocs-ui/page";

import { notFound } from "next/navigation";
import { getMDXComponents } from "@/mdx-components";
import type { Metadata } from "next";
import { createRelativeLink } from "fumadocs-ui/mdx";

export default async function Page(props: PageProps<"/docs/[[...slug]]">) {
  const params = await props.params;
  const page = source.getPage(params.slug);
  if (!page) notFound();

  const MDX = page.data.body;

  return (
    <DocsPage toc={page.data.toc} full={page.data.full}>
      <DocsTitle>{page.data.title}</DocsTitle>
      <DocsDescription>{page.data.description}</DocsDescription>
      <DocsBody>
        <MDX
          components={getMDXComponents({
            a: createRelativeLink(source, page),
          })}
        />
      </DocsBody>
    </DocsPage>
  );
}

export async function generateStaticParams() {
  return source.generateParams();
}
import { source } from '@/lib/source';
import { createFromSource } from 'fumadocs-core/search/server';

export const { GET } = createFromSource(source, {
  language: 'english',
});

The search is powered by Orama, learn more about Document Search.

Finish

You can start the dev server and create MDX files.

---
title: Hello World
---

## Introduction

Overview

It's common for developer tool related docs to version their docs, such as different docs for v1 and v2 of the same tool.

Fumadocs provide the primitives for you to implement versioning on your own way.

Partial Versioning

When versioning only applies to part of your docs, You can separate them by folders.

For example:

getting-started.mdx
getting-started.mdx

Good to Know

You may want to group them with tabs rather than folders using Sidebar Tabs.

Full Versioning

Sometimes you want to version the entire website, such as https://v14.fumadocs.dev (Fumadocs v14) and https://fumadocs.dev (Latest Fumadocs). You can create a Git branch for a version of docs (call it v2 for example), and deploy it as a separate app on another subdomain like v2.my-site.com.

Optionally, you can link to the other versions from your docs. This design allows some advantages over partial versioning:

  • Easy maintenance: Old docs/branches won't be affected when you iterate or upgrade dependencies.
  • Better consistency: Not just the docs itself, your landing page (and other pages) will also be versioned.