Search

Search documentation

Arch

Fumadocs Setup Guide

Step-by-step guide to set up Fumadocs documentation from scratch.

This guide walks through setting up Fumadocs documentation from scratch, following the official documentation.


Phase 1: Install & Configure Core

Install Packages

What: Install Fumadocs core packages

Why: These provide MDX processing, page tree generation, and UI components

pnpm add fumadocs-mdx fumadocs-core fumadocs-ui @types/mdx

Create source.config.ts

What: Configure where your MDX content lives

Why: Fumadocs MDX uses this to generate the .source folder with type-safe collections

// source.config.ts (root)
import { defineDocs, defineConfig } from "fumadocs-mdx/config";

export const docs = defineDocs({
  dir: "content/docs",
});

export default defineConfig();

Update Next.js Config

What: Rename next.config.tsnext.config.mjs and add Fumadocs MDX plugin

Why: Fumadocs MDX is ESM-only; the plugin handles MDX compilation

// next.config.mjs
import { createMDX } from "fumadocs-mdx/next";

const config = {
  reactStrictMode: true,
};

const withMDX = createMDX();

export default withMDX(config);

Update tsconfig.json

What: Add path alias for Fumadocs collections

Why: Enables clean imports like fumadocs-mdx:collections/server

{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/*"],
      "fumadocs-mdx:collections/*": [".source/*"]
    }
  }
}

Phase 2: Root Layout & Styles

Update globals.css

What: Import Fumadocs UI styles

Why: Provides the documentation theme and component styles

/* src/app/globals.css */
@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/preset.css";

/* Your existing styles below */

Update Root Layout

What: Wrap app in RootProvider

Why: Provides theme, search, and context for Fumadocs components

// src/app/layout.tsx
import { RootProvider } from "fumadocs-ui/provider/next";
import type { ReactNode } from "react";
import "./globals.css";

export default function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className="flex flex-col min-h-screen">
        <RootProvider>{children}</RootProvider>
      </body>
    </html>
  );
}

Create mdx-components.tsx

What: Register MDX components globally

Why: Allows MDX to use Fumadocs UI components (Cards, Callouts, Tabs, etc.)

// mdx-components.tsx (root)
import defaultMdxComponents from "fumadocs-ui/mdx";
import type { MDXComponents } from "mdx/types";

export function getMDXComponents(components?: MDXComponents): MDXComponents {
  return {
    ...defaultMdxComponents,
    ...components,
  };
}

Phase 3: Source & Docs Layout

Create lib/source.ts

What: Export the docs source with page tree

Why: This connects your MDX content to Fumadocs routing

// src/lib/source.ts
import { docs } from "fumadocs-mdx:collections/server";
import { loader } from "fumadocs-core/source";

export const source = loader({
  baseUrl: "/docs",
  source: docs.toFumadocsSource(),
});

Create lib/layout.shared.tsx

What: Shared layout options (nav title, links)

Why: DRY config for navbar across layouts

// src/lib/layout.shared.tsx
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";

export function baseOptions(): BaseLayoutProps {
  return {
    nav: {
      title: "Evolphin UI",
    },
    links: [{ text: "Docs", url: "/docs", active: "nested-url" }],
  };
}

Create Docs Layout

What: Sidebar + content layout for docs pages

Why: Provides standard documentation UX with navigation

// src/app/docs/layout.tsx
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { baseOptions } from "@/lib/layout.shared";
import { source } from "@/lib/source";
import type { ReactNode } from "react";

export default function Layout({ children }: { children: ReactNode }) {
  return (
    <DocsLayout {...baseOptions()} tree={source.pageTree}>
      {children}
    </DocsLayout>
  );
}

Create Docs Page

What: Dynamic route that renders MDX content

Why: Catches all /docs/* routes and renders the correct page

// src/app/docs/[[...slug]]/page.tsx
import { source } from "@/lib/source";
import {
  DocsPage,
  DocsBody,
  DocsTitle,
  DocsDescription,
} from "fumadocs-ui/page";
import { notFound } from "next/navigation";
import defaultMdxComponents from "fumadocs-ui/mdx";

export default async function Page({
  params,
}: {
  params: Promise<{ slug?: string[] }>;
}) {
  const { slug } = await params;
  const page = source.getPage(slug);
  if (!page) notFound();

  const MDX = page.data.body;

  return (
    <DocsPage toc={page.data.toc}>
      <DocsTitle>{page.data.title}</DocsTitle>
      <DocsDescription>{page.data.description}</DocsDescription>
      <DocsBody>
        <MDX components={defaultMdxComponents} />
      </DocsBody>
    </DocsPage>
  );
}

export function generateStaticParams() {
  return source.generateParams();
}

Phase 4: Content Structure

Create Index Page

Create content/docs/index.mdx:

---
title: Welcome to Evolphin UI
description: A beautiful, modern component library built on shadcn/ui
---

## Getting Started

Welcome to the Evolphin UI documentation.

Create Meta File

Create content/docs/meta.json:

{
  "title": "Documentation",
  "pages": ["index", "..."]
}

The "..." means "include all other pages automatically".


Phase 5: Verify

  1. Stop any running dev server
  2. Delete .next folder (clean build)
  3. Run pnpm dev
  4. Visit http://localhost:3000/docs

What You Get

FeatureStatus
MDX content in content/docs/
Sidebar navigation
Search (Orama, Ctrl+K)
Dark/light theme toggle
Table of contents
Code syntax highlighting
Cards, Callouts, Tabs, Steps

On this page